@saptools/cf-debugger 0.2.0 → 0.2.1
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/{chunk-ZWAQD7KL.js → chunk-AKQR4Y74.js} +167 -101
- package/dist/chunk-AKQR4Y74.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ZWAQD7KL.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
startupTimeoutError,
|
|
20
20
|
stopAllDebuggers,
|
|
21
21
|
stopDebugger
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-AKQR4Y74.js";
|
|
23
23
|
|
|
24
24
|
// src/cli.ts
|
|
25
25
|
import nodeProcess from "process";
|
|
@@ -28,7 +28,7 @@ import { Command } from "commander";
|
|
|
28
28
|
// package.json
|
|
29
29
|
var package_default = {
|
|
30
30
|
name: "@saptools/cf-debugger",
|
|
31
|
-
version: "0.2.
|
|
31
|
+
version: "0.2.1",
|
|
32
32
|
description: "Open an SSH debug tunnel to a SAP BTP Cloud Foundry app's Node.js inspector \u2014 from any terminal, no IDE required.",
|
|
33
33
|
type: "module",
|
|
34
34
|
publishConfig: {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\n\nimport nodeProcess from \"node:process\";\n\nimport { Command } from \"commander\";\n\nimport packageMetadata from \"../package.json\" with { type: \"json\" };\n\nimport { readCurrentCfTarget, requireCurrentCfRegion } from \"./cf.js\";\nimport type { CurrentCfTargetReadOptions } from \"./cf.js\";\nimport {\n CLEANUP_FAILURE_EXIT_CODE,\n cliErrorExitCode,\n hasTunnelTerminationFailure,\n} from \"./cli-errors.js\";\nimport {\n DEFAULT_NODE_INSPECTOR_PORT,\n resolveNodeTarget,\n} from \"./cloud-foundry/node-process.js\";\nimport { runDoctor } from \"./debug-session/doctor.js\";\nimport { getDebuggerHandleTunnelError } from \"./debug-session/lifecycle.js\";\nimport { startDebuggerWithinDeadline } from \"./debug-session/start.js\";\nimport {\n createStartupDeadline,\n remainingStartupMs,\n resolveStartupTimeoutMs,\n startupTimeoutError,\n} from \"./debug-session/startup-deadline.js\";\nimport {\n getSession,\n listSessions,\n stopAllDebuggers,\n stopDebugger,\n} from \"./debugger.js\";\nimport type {\n DebuggerHandle,\n ResolvedSessionKey,\n SessionStatus,\n StartDebuggerOptions,\n} from \"./types.js\";\nimport { CfDebuggerError } from \"./types.js\";\n\nfunction readRequiredOption(value: string | undefined, flag: string): string {\n if (value === undefined || value.trim().length === 0) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", `Missing required option ${flag}.`);\n }\n return value;\n}\n\nfunction parseOptionalInteger(\n raw: string | undefined,\n label: string,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\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 || value > maximum) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n `${label} must be from ${minimum.toString()} to ${maximum.toString()}.`,\n );\n }\n return value;\n}\n\nfunction parseSeconds(raw: string | undefined, label: string): number | undefined {\n const seconds = parseOptionalInteger(raw, label, 1);\n return seconds === undefined ? undefined : seconds * 1000;\n}\n\ninterface TargetCommandOptions {\n readonly process?: string;\n readonly instance?: string;\n readonly nodePid?: string;\n readonly apiEndpoint?: 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 remotePort?: string;\n readonly timeout?: string;\n readonly startupTimeout?: string;\n readonly allowSshEnableRestart?: boolean;\n readonly sshEnableRestart?: boolean;\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 readonly force?: boolean;\n}\n\ntype StatusCommandOptions = Omit<StopCommandOptions, \"all\" | \"force\">;\nconst STOP_SCOPE_OPTION_NAMES = [\n \"apiEndpoint\",\n \"app\",\n \"instance\",\n \"nodePid\",\n \"org\",\n \"process\",\n \"region\",\n \"sessionId\",\n \"space\",\n] as const;\n\nfunction logStatus(verbose: boolean, status: SessionStatus, message?: string): void {\n if (!verbose) {\n return;\n }\n const suffix = message === undefined ? \"\" : `: ${message}`;\n nodeProcess.stdout.write(`[cf-debugger] ${status}${suffix}\\n`);\n}\n\nfunction mergeSelector<\n T extends { region?: string; org?: string; space?: string; app?: string },\n>(selector: string | undefined, options: T): T {\n if (selector === undefined) {\n return options;\n }\n const parts = selector.split(\"/\");\n if (parts.length === 1 && parts[0]?.length !== 0) {\n return { ...options, app: options.app ?? parts[0] };\n }\n if (parts.length === 4 && parts.every((part) => part.length > 0)) {\n return {\n ...options,\n region: options.region ?? parts[0],\n org: options.org ?? parts[1],\n space: options.space ?? parts[2],\n app: options.app ?? parts[3],\n };\n }\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"Invalid app selector. Expected <app> or non-empty <region>/<org>/<space>/<app> segments.\",\n );\n}\n\ninterface StartupAbort {\n readonly signal: AbortSignal;\n requestedExitCode(): number | undefined;\n dispose(): void;\n}\n\nfunction startupAbort(app: string): StartupAbort {\n const controller = new AbortController();\n let requestedExitCode: number | undefined;\n const handler = (exitCode: number) => (): void => {\n requestedExitCode ??= exitCode;\n controller.abort();\n nodeProcess.stderr.write(`\\nAborting startup for ${app}...\\n`);\n };\n const onSigint = handler(130);\n const onSigterm = handler(143);\n nodeProcess.on(\"SIGINT\", onSigint);\n nodeProcess.on(\"SIGTERM\", onSigterm);\n return {\n signal: controller.signal,\n requestedExitCode: (): number | undefined => requestedExitCode,\n dispose: (): void => {\n nodeProcess.off(\"SIGINT\", onSigint);\n nodeProcess.off(\"SIGTERM\", onSigterm);\n },\n };\n}\n\nfunction writeReady(\n app: string,\n key: ResolvedSessionKey,\n handle: DebuggerHandle,\n): void {\n nodeProcess.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 writeCleanupError(error: unknown): void {\n const message = error instanceof Error ? error.message : String(error);\n nodeProcess.stderr.write(`Error during stop: ${message}\\n`);\n}\n\nasync function waitForHandle(\n app: string,\n handle: DebuggerHandle,\n): Promise<void> {\n let pendingDispose: Promise<void> | undefined;\n let requestedExitCode: number | undefined;\n const dispose = (): Promise<void> => {\n pendingDispose ??= (async (): Promise<void> => {\n nodeProcess.stdout.write(`\\nStopping debugger for ${app}...\\n`);\n await handle.dispose();\n })();\n return pendingDispose;\n };\n const stop = (exitCode: number) => (): void => {\n requestedExitCode = exitCode;\n void dispose()\n .catch((error: unknown) => {\n writeCleanupError(error);\n nodeProcess.exit(CLEANUP_FAILURE_EXIT_CODE);\n });\n };\n nodeProcess.on(\"SIGINT\", stop(130));\n nodeProcess.on(\"SIGTERM\", stop(143));\n const code = await handle.waitForExit();\n const tunnelError = getDebuggerHandleTunnelError(handle);\n if (tunnelError !== undefined) {\n nodeProcess.stderr.write(\n `Error [${tunnelError.code}]: ${tunnelError.message}\\n`,\n );\n if (tunnelError.stderr !== undefined && tunnelError.stderr.trim().length > 0) {\n nodeProcess.stderr.write(`[cf-debugger transport]\\n${tunnelError.stderr.trim()}\\n`);\n }\n }\n try {\n await dispose();\n } catch (error: unknown) {\n writeCleanupError(error);\n nodeProcess.exit(CLEANUP_FAILURE_EXIT_CODE);\n }\n nodeProcess.exit(requestedExitCode ?? code ?? 0);\n}\n\ntype RestartEnvironment = \"allow\" | \"forbid\" | \"unset\";\n\nfunction parseRestartEnvironment(): RestartEnvironment {\n const value = nodeProcess.env[\"CF_DEBUGGER_ALLOW_RESTART\"];\n if (value === undefined) {\n return \"unset\";\n }\n if (value === \"0\") {\n return \"forbid\";\n }\n if (value === \"1\") {\n return \"allow\";\n }\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"CF_DEBUGGER_ALLOW_RESTART must be 0 or 1.\",\n );\n}\n\nfunction buildStartOptions(\n options: StartCommandOptions,\n key: ResolvedSessionKey,\n app: string,\n signal: AbortSignal,\n startupTimeoutMs: number,\n): StartDebuggerOptions {\n const preferredPort = parseOptionalInteger(options.port, \"port\", 1, 65_535);\n const remotePort = parseOptionalInteger(options.remotePort, \"remotePort\", 1, 65_535);\n const nodePid = parseOptionalInteger(options.nodePid, \"nodePid\", 1);\n const tunnelReadyTimeoutMs = parseSeconds(options.timeout, \"timeout\");\n const restartEnvironment = parseRestartEnvironment();\n const allowSshEnableRestart =\n options.sshEnableRestart !== false &&\n restartEnvironment !== \"forbid\" &&\n (options.allowSshEnableRestart === true || restartEnvironment === \"allow\");\n return {\n region: key.region,\n org: key.org,\n space: key.space,\n app,\n process: key.process,\n instance: key.instance,\n signal,\n allowSshEnableRestart,\n ...(options.apiEndpoint === undefined ? {} : { apiEndpoint: options.apiEndpoint }),\n ...(preferredPort === undefined ? {} : { preferredPort }),\n ...(remotePort === undefined ? {} : { remotePort }),\n ...(nodePid === undefined ? {} : { nodePid }),\n ...(tunnelReadyTimeoutMs === undefined ? {} : { tunnelReadyTimeoutMs }),\n startupTimeoutMs,\n };\n}\n\nfunction deadlineTimedOut(\n deadline: ReturnType<typeof createStartupDeadline>,\n): boolean {\n return remainingStartupMs(deadline.expiresAt) === 0 ||\n (\n deadline.signal.reason instanceof CfDebuggerError &&\n deadline.signal.reason.code === \"STARTUP_TIMEOUT\"\n );\n}\n\nasync function handleStart(\n selector: string | undefined,\n rawOptions: StartCommandOptions,\n): Promise<void> {\n const options = mergeSelector(selector, rawOptions);\n const app = readRequiredOption(options.app, \"--app or selector\");\n const verbose = options.verbose ?? false;\n const startupTimeoutMs = resolveStartupTimeoutMs(\n parseSeconds(options.startupTimeout, \"startupTimeout\"),\n );\n const abort = startupAbort(app);\n const deadline = createStartupDeadline(startupTimeoutMs, abort.signal);\n let handle;\n let phase = \"current CF target discovery\";\n let key: ResolvedSessionKey;\n try {\n key = await resolveSessionKey({ ...options, app }, deadline.signal);\n if (deadlineTimedOut(deadline)) {\n throw startupTimeoutError(startupTimeoutMs, phase);\n }\n phase = \"startup\";\n handle = await startDebuggerWithinDeadline({\n ...buildStartOptions(options, key, app, deadline.signal, startupTimeoutMs),\n verbose,\n onStatus: (status, message): void => {\n logStatus(verbose, status, message);\n },\n }, deadline);\n } catch (error: unknown) {\n const normalized = deadlineTimedOut(deadline) &&\n !(error instanceof CfDebuggerError && error.code === \"STARTUP_TIMEOUT\")\n ? startupTimeoutError(startupTimeoutMs, phase)\n : error;\n const exitCode = abort.requestedExitCode();\n if (exitCode !== undefined && typeof normalized === \"object\" && normalized !== null) {\n Reflect.set(normalized, \"cliExitCode\", exitCode);\n }\n throw normalized;\n } finally {\n deadline.dispose();\n abort.dispose();\n }\n writeReady(app, key, handle);\n await waitForHandle(app, handle);\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(signal?: AbortSignal): CurrentCfTargetReadOptions | undefined {\n const command = nodeProcess.env[\"CF_DEBUGGER_CF_BIN\"];\n if (command === undefined && signal === undefined) {\n return undefined;\n }\n return {\n ...(command === undefined ? {} : { command }),\n ...(signal === undefined ? {} : { signal }),\n };\n}\n\nasync function resolveSessionKey(\n options: StopCommandOptions,\n signal?: AbortSignal,\n): Promise<ResolvedSessionKey> {\n const app = readRequiredOption(options.app, \"--app or selector\");\n const region = optionalText(options.region);\n const org = optionalText(options.org);\n const space = optionalText(options.space);\n const nodePid = parseOptionalInteger(options.nodePid, \"nodePid\", 1);\n const instance = parseOptionalInteger(options.instance, \"instance\", 0);\n const target = resolveNodeTarget({\n ...(options.process === undefined ? {} : { process: options.process }),\n ...(instance === undefined ? {} : { instance }),\n ...(nodePid === undefined ? {} : { nodePid }),\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 ...(options.apiEndpoint === undefined ? {} : { apiEndpoint: options.apiEndpoint }),\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n };\n }\n const current = await readCurrentCfTarget(currentCfOptions(signal)).catch((error: unknown) => {\n if (\n error instanceof CfDebuggerError &&\n (error.code === \"ABORTED\" || error.code === \"STARTUP_TIMEOUT\")\n ) {\n throw error;\n }\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n \"No current CF target. 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. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\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 ...(options.apiEndpoint === undefined ? {} : { apiEndpoint: options.apiEndpoint }),\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n };\n}\n\nasync function resolveOptionalSessionKey(\n options: StopCommandOptions,\n): Promise<ResolvedSessionKey | undefined> {\n if (optionalText(options.app) === undefined) {\n if (\n optionalText(options.region) !== undefined ||\n optionalText(options.org) !== undefined ||\n optionalText(options.space) !== undefined\n ) {\n readRequiredOption(options.app, \"--app\");\n }\n return undefined;\n }\n return await resolveSessionKey(options);\n}\n\nfunction writeStopResult(result: Awaited<ReturnType<typeof stopDebugger>>): void {\n if (result === undefined) {\n return;\n }\n if (result.warning !== undefined) {\n nodeProcess.stderr.write(`[cf-debugger] warning: ${result.warning}\\n`);\n }\n if (result.pending) {\n nodeProcess.stdout.write(\n `Stop requested for session ${result.sessionId} (${result.app}, phase ${result.status}).\\n`,\n );\n } else if (result.stale) {\n nodeProcess.stdout.write(\n `Removed ${result.forced ? \"forced \" : \"\"}stale session ${result.sessionId} ` +\n `(${result.app}, port ${result.localPort.toString()}).\\n`,\n );\n } else {\n nodeProcess.stdout.write(\n `Stopped session ${result.sessionId} (${result.app}, port ${result.localPort.toString()}).\\n`,\n );\n }\n}\n\nasync function handleStop(\n selector: string | undefined,\n rawOptions: StopCommandOptions,\n command: Command,\n): Promise<void> {\n if (\n rawOptions.all === true &&\n (\n selector !== undefined ||\n STOP_SCOPE_OPTION_NAMES.some((name) => command.getOptionValueSource(name) === \"cli\")\n )\n ) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"--all cannot be combined with a selector, --session-id, or target selector options.\",\n );\n }\n const options = mergeSelector(selector, rawOptions);\n if (options.all === true) {\n const summary = await stopAllDebuggers(options.force === true);\n for (const outcome of summary.outcomes) {\n if (outcome.error === undefined) {\n writeStopResult(outcome.result);\n } else {\n nodeProcess.stderr.write(\n `Failed ${outcome.sessionId} (${outcome.app}): ${outcome.error.message}\\n`,\n );\n }\n }\n nodeProcess.stdout.write(\n `Stop summary: ${summary.stopped.toString()} stopped, ${summary.stale.toString()} stale, ` +\n `${summary.pending.toString()} pending, ${summary.failed.toString()} failed.\\n`,\n );\n if (summary.failed > 0) {\n nodeProcess.exitCode = 1;\n }\n return;\n }\n const key = await resolveOptionalSessionKey(options);\n const result = await stopDebugger({\n ...(options.sessionId === undefined ? {} : { sessionId: options.sessionId }),\n ...(key === undefined ? {} : { key }),\n force: options.force === true,\n });\n if (result === undefined) {\n throw new CfDebuggerError(\n \"SESSION_NOT_FOUND\",\n \"No matching session. Use `cf-debugger list` and pass --session-id or an exact key.\",\n );\n }\n writeStopResult(result);\n}\n\nasync function handleList(): Promise<void> {\n nodeProcess.stdout.write(`${JSON.stringify(await listSessions(), null, 2)}\\n`);\n}\n\nasync function handleStatus(\n selector: string | undefined,\n rawOptions: StatusCommandOptions,\n): Promise<void> {\n const options = mergeSelector(selector, rawOptions);\n const session = options.sessionId === undefined\n ? await getSession(await resolveSessionKey(options))\n : (await listSessions()).find((candidate) => candidate.sessionId === options.sessionId);\n nodeProcess.stdout.write(`${JSON.stringify(session ?? null, null, 2)}\\n`);\n}\n\nasync function handleDoctor(cleanup: boolean): Promise<void> {\n const report = await runDoctor({ cleanup });\n nodeProcess.stdout.write(`${JSON.stringify(report, 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> or <region>/<org>/<space>/<app>\")\n .option(\"--region <key>\", \"CF region key (default: current cf target)\")\n .option(\"--api-endpoint <url>\", \"Explicit CF API endpoint override\")\n .option(\"--org <name>\", \"CF org (default: current cf target)\")\n .option(\"--space <name>\", \"CF space (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\", \"0\")\n .option(\"--node-pid <pid>\", \"Explicit remote Node.js PID\")\n .option(\"--port <number>\", \"Preferred local port\")\n .option(\n \"--remote-port <number>\",\n \"Remote inspector port\",\n DEFAULT_NODE_INSPECTOR_PORT.toString(),\n )\n .option(\"--timeout <seconds>\", \"Tunnel/inspector readiness timeout\", \"180\")\n .option(\"--startup-timeout <seconds>\", \"Overall startup deadline\", \"300\")\n .option(\n \"--allow-ssh-enable-restart\",\n \"Allow app-level SSH enablement and an app restart (opt-in)\",\n )\n .option(\n \"--no-ssh-enable-restart\",\n \"Forbid app-level SSH enablement and restart, overriding flag/environment\",\n )\n .option(\"--verbose\", \"Print status transitions and tunnel diagnostics\", false)\n .action(async (selector: string | undefined, options: StartCommandOptions): Promise<void> => {\n await handleStart(selector, options);\n });\n}\n\nfunction addKeyOptions(command: Command): Command {\n return command\n .option(\"--region <key>\")\n .option(\"--api-endpoint <url>\", \"Exact API endpoint selector\")\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\", \"0\")\n .option(\"--node-pid <pid>\", \"Exact remote Node PID selector\");\n}\n\nfunction registerStopCommand(program: Command): void {\n addKeyOptions(\n program\n .command(\"stop\")\n .description(\"Stop one session by exact key/id, or every session with --all\")\n .argument(\"[selector]\", \"Optional <app> or <region>/<org>/<space>/<app>\"),\n )\n .option(\"--session-id <id>\")\n .option(\n \"--all\",\n \"Attempt every active session; cannot be combined with session selectors\",\n false,\n )\n .option(\n \"--force\",\n \"Forget unverifiable state and its owned CF home; never signal an unverified process\",\n false,\n )\n .action(\n async (\n selector: string | undefined,\n options: StopCommandOptions,\n command: Command,\n ): Promise<void> => {\n await handleStop(selector, options, command);\n },\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 addKeyOptions(\n program\n .command(\"status\")\n .description(\"Print one exact session as JSON; null only when no session matches\")\n .argument(\"[selector]\", \"Optional <app> or <region>/<org>/<space>/<app>\"),\n )\n .option(\"--session-id <id>\", \"Exact session ID selector\")\n .action(async (selector: string | undefined, options: StatusCommandOptions): Promise<void> => {\n await handleStatus(selector, options);\n });\n program\n .command(\"doctor\")\n .description(\"Report session health, orphan homes/ports, temp files, and legacy credentials\")\n .option(\"--cleanup\", \"Remove only safe orphan v2 homes and stale v2 temp/lock files\", false)\n .action(async (options: { readonly cleanup?: boolean }): Promise<void> => {\n await handleDoctor(options.cleanup === true);\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 Node.js inspector\")\n .version(packageMetadata.version);\n registerStartCommand(program);\n registerStopCommand(program);\n registerReadCommands(program);\n await program.parseAsync([...argv]);\n}\n\nfunction writeTopLevelError(error: unknown): void {\n if (error instanceof CfDebuggerError) {\n if (error.code === \"ABORTED\") {\n nodeProcess.stderr.write(`Aborted: ${error.message}\\n`);\n nodeProcess.exit(cliErrorExitCode(error));\n }\n nodeProcess.stderr.write(`Error [${error.code}]: ${error.message}\\n`);\n if (error.stderr !== undefined && error.stderr.trim().length > 0) {\n nodeProcess.stderr.write(`[cf-debugger transport]\\n${error.stderr.trim()}\\n`);\n }\n nodeProcess.exit(cliErrorExitCode(error));\n }\n if (hasTunnelTerminationFailure(error)) {\n const message = error instanceof Error ? error.message : String(error);\n nodeProcess.stderr.write(`Error during cleanup: ${message}\\n`);\n nodeProcess.exit(CLEANUP_FAILURE_EXIT_CODE);\n }\n const message = error instanceof Error ? error.message : String(error);\n nodeProcess.stderr.write(`Error: ${message}\\n`);\n nodeProcess.exit(cliErrorExitCode(error));\n}\n\ntry {\n await main(nodeProcess.argv);\n} catch (error: unknown) {\n writeTopLevelError(error);\n}\n","{\n \"name\": \"@saptools/cf-debugger\",\n \"version\": \"0.2.0\",\n \"description\": \"Open an SSH debug tunnel to a SAP BTP Cloud Foundry app's Node.js inspector — from any terminal, no IDE required.\",\n \"type\": \"module\",\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"bin\": {\n \"cf-debugger\": \"dist/cli.js\"\n },\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"eslint src tests\",\n \"test:unit\": \"vitest run --coverage\",\n \"test:e2e\": \"playwright test\"\n },\n \"keywords\": [\n \"sap\",\n \"cloud-foundry\",\n \"btp\",\n \"debug\",\n \"debugger\",\n \"ssh-tunnel\",\n \"node-inspector\",\n \"cli\",\n \"saptools\"\n ],\n \"author\": \"Dong Tran\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/dongitran/saptools.git\",\n \"directory\": \"packages/cf-debugger\"\n },\n \"homepage\": \"https://github.com/dongitran/saptools/tree/main/packages/cf-debugger#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/dongitran/saptools/issues\"\n },\n \"dependencies\": {\n \"commander\": \"^13.0.0\"\n },\n \"devDependencies\": {\n \"@playwright/test\": \"^1.50.0\",\n \"@vitest/coverage-v8\": \"^3.0.0\",\n \"tsup\": \"^8.3.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n"],"mappings":"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","names":["message"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\n\nimport nodeProcess from \"node:process\";\n\nimport { Command } from \"commander\";\n\nimport packageMetadata from \"../package.json\" with { type: \"json\" };\n\nimport { readCurrentCfTarget, requireCurrentCfRegion } from \"./cf.js\";\nimport type { CurrentCfTargetReadOptions } from \"./cf.js\";\nimport {\n CLEANUP_FAILURE_EXIT_CODE,\n cliErrorExitCode,\n hasTunnelTerminationFailure,\n} from \"./cli-errors.js\";\nimport {\n DEFAULT_NODE_INSPECTOR_PORT,\n resolveNodeTarget,\n} from \"./cloud-foundry/node-process.js\";\nimport { runDoctor } from \"./debug-session/doctor.js\";\nimport { getDebuggerHandleTunnelError } from \"./debug-session/lifecycle.js\";\nimport { startDebuggerWithinDeadline } from \"./debug-session/start.js\";\nimport {\n createStartupDeadline,\n remainingStartupMs,\n resolveStartupTimeoutMs,\n startupTimeoutError,\n} from \"./debug-session/startup-deadline.js\";\nimport {\n getSession,\n listSessions,\n stopAllDebuggers,\n stopDebugger,\n} from \"./debugger.js\";\nimport type {\n DebuggerHandle,\n ResolvedSessionKey,\n SessionStatus,\n StartDebuggerOptions,\n} from \"./types.js\";\nimport { CfDebuggerError } from \"./types.js\";\n\nfunction readRequiredOption(value: string | undefined, flag: string): string {\n if (value === undefined || value.trim().length === 0) {\n throw new CfDebuggerError(\"UNSAFE_INPUT\", `Missing required option ${flag}.`);\n }\n return value;\n}\n\nfunction parseOptionalInteger(\n raw: string | undefined,\n label: string,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\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 || value > maximum) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n `${label} must be from ${minimum.toString()} to ${maximum.toString()}.`,\n );\n }\n return value;\n}\n\nfunction parseSeconds(raw: string | undefined, label: string): number | undefined {\n const seconds = parseOptionalInteger(raw, label, 1);\n return seconds === undefined ? undefined : seconds * 1000;\n}\n\ninterface TargetCommandOptions {\n readonly process?: string;\n readonly instance?: string;\n readonly nodePid?: string;\n readonly apiEndpoint?: 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 remotePort?: string;\n readonly timeout?: string;\n readonly startupTimeout?: string;\n readonly allowSshEnableRestart?: boolean;\n readonly sshEnableRestart?: boolean;\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 readonly force?: boolean;\n}\n\ntype StatusCommandOptions = Omit<StopCommandOptions, \"all\" | \"force\">;\nconst STOP_SCOPE_OPTION_NAMES = [\n \"apiEndpoint\",\n \"app\",\n \"instance\",\n \"nodePid\",\n \"org\",\n \"process\",\n \"region\",\n \"sessionId\",\n \"space\",\n] as const;\n\nfunction logStatus(verbose: boolean, status: SessionStatus, message?: string): void {\n if (!verbose) {\n return;\n }\n const suffix = message === undefined ? \"\" : `: ${message}`;\n nodeProcess.stdout.write(`[cf-debugger] ${status}${suffix}\\n`);\n}\n\nfunction mergeSelector<\n T extends { region?: string; org?: string; space?: string; app?: string },\n>(selector: string | undefined, options: T): T {\n if (selector === undefined) {\n return options;\n }\n const parts = selector.split(\"/\");\n if (parts.length === 1 && parts[0]?.length !== 0) {\n return { ...options, app: options.app ?? parts[0] };\n }\n if (parts.length === 4 && parts.every((part) => part.length > 0)) {\n return {\n ...options,\n region: options.region ?? parts[0],\n org: options.org ?? parts[1],\n space: options.space ?? parts[2],\n app: options.app ?? parts[3],\n };\n }\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"Invalid app selector. Expected <app> or non-empty <region>/<org>/<space>/<app> segments.\",\n );\n}\n\ninterface StartupAbort {\n readonly signal: AbortSignal;\n requestedExitCode(): number | undefined;\n dispose(): void;\n}\n\nfunction startupAbort(app: string): StartupAbort {\n const controller = new AbortController();\n let requestedExitCode: number | undefined;\n const handler = (exitCode: number) => (): void => {\n requestedExitCode ??= exitCode;\n controller.abort();\n nodeProcess.stderr.write(`\\nAborting startup for ${app}...\\n`);\n };\n const onSigint = handler(130);\n const onSigterm = handler(143);\n nodeProcess.on(\"SIGINT\", onSigint);\n nodeProcess.on(\"SIGTERM\", onSigterm);\n return {\n signal: controller.signal,\n requestedExitCode: (): number | undefined => requestedExitCode,\n dispose: (): void => {\n nodeProcess.off(\"SIGINT\", onSigint);\n nodeProcess.off(\"SIGTERM\", onSigterm);\n },\n };\n}\n\nfunction writeReady(\n app: string,\n key: ResolvedSessionKey,\n handle: DebuggerHandle,\n): void {\n nodeProcess.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 writeCleanupError(error: unknown): void {\n const message = error instanceof Error ? error.message : String(error);\n nodeProcess.stderr.write(`Error during stop: ${message}\\n`);\n}\n\nasync function waitForHandle(\n app: string,\n handle: DebuggerHandle,\n): Promise<void> {\n let pendingDispose: Promise<void> | undefined;\n let requestedExitCode: number | undefined;\n const dispose = (): Promise<void> => {\n pendingDispose ??= (async (): Promise<void> => {\n nodeProcess.stdout.write(`\\nStopping debugger for ${app}...\\n`);\n await handle.dispose();\n })();\n return pendingDispose;\n };\n const stop = (exitCode: number) => (): void => {\n requestedExitCode = exitCode;\n void dispose()\n .catch((error: unknown) => {\n writeCleanupError(error);\n nodeProcess.exit(CLEANUP_FAILURE_EXIT_CODE);\n });\n };\n nodeProcess.on(\"SIGINT\", stop(130));\n nodeProcess.on(\"SIGTERM\", stop(143));\n const code = await handle.waitForExit();\n const tunnelError = getDebuggerHandleTunnelError(handle);\n if (tunnelError !== undefined) {\n nodeProcess.stderr.write(\n `Error [${tunnelError.code}]: ${tunnelError.message}\\n`,\n );\n if (tunnelError.stderr !== undefined && tunnelError.stderr.trim().length > 0) {\n nodeProcess.stderr.write(`[cf-debugger transport]\\n${tunnelError.stderr.trim()}\\n`);\n }\n }\n try {\n await dispose();\n } catch (error: unknown) {\n writeCleanupError(error);\n nodeProcess.exit(CLEANUP_FAILURE_EXIT_CODE);\n }\n nodeProcess.exit(requestedExitCode ?? code ?? 0);\n}\n\ntype RestartEnvironment = \"allow\" | \"forbid\" | \"unset\";\n\nfunction parseRestartEnvironment(): RestartEnvironment {\n const value = nodeProcess.env[\"CF_DEBUGGER_ALLOW_RESTART\"];\n if (value === undefined) {\n return \"unset\";\n }\n if (value === \"0\") {\n return \"forbid\";\n }\n if (value === \"1\") {\n return \"allow\";\n }\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"CF_DEBUGGER_ALLOW_RESTART must be 0 or 1.\",\n );\n}\n\nfunction buildStartOptions(\n options: StartCommandOptions,\n key: ResolvedSessionKey,\n app: string,\n signal: AbortSignal,\n startupTimeoutMs: number,\n): StartDebuggerOptions {\n const preferredPort = parseOptionalInteger(options.port, \"port\", 1, 65_535);\n const remotePort = parseOptionalInteger(options.remotePort, \"remotePort\", 1, 65_535);\n const nodePid = parseOptionalInteger(options.nodePid, \"nodePid\", 1);\n const tunnelReadyTimeoutMs = parseSeconds(options.timeout, \"timeout\");\n const restartEnvironment = parseRestartEnvironment();\n const allowSshEnableRestart =\n options.sshEnableRestart !== false &&\n restartEnvironment !== \"forbid\" &&\n (options.allowSshEnableRestart === true || restartEnvironment === \"allow\");\n return {\n region: key.region,\n org: key.org,\n space: key.space,\n app,\n process: key.process,\n instance: key.instance,\n signal,\n allowSshEnableRestart,\n ...(options.apiEndpoint === undefined ? {} : { apiEndpoint: options.apiEndpoint }),\n ...(preferredPort === undefined ? {} : { preferredPort }),\n ...(remotePort === undefined ? {} : { remotePort }),\n ...(nodePid === undefined ? {} : { nodePid }),\n ...(tunnelReadyTimeoutMs === undefined ? {} : { tunnelReadyTimeoutMs }),\n startupTimeoutMs,\n };\n}\n\nfunction deadlineTimedOut(\n deadline: ReturnType<typeof createStartupDeadline>,\n): boolean {\n return remainingStartupMs(deadline.expiresAt) === 0 ||\n (\n deadline.signal.reason instanceof CfDebuggerError &&\n deadline.signal.reason.code === \"STARTUP_TIMEOUT\"\n );\n}\n\nasync function handleStart(\n selector: string | undefined,\n rawOptions: StartCommandOptions,\n): Promise<void> {\n const options = mergeSelector(selector, rawOptions);\n const app = readRequiredOption(options.app, \"--app or selector\");\n const verbose = options.verbose ?? false;\n const startupTimeoutMs = resolveStartupTimeoutMs(\n parseSeconds(options.startupTimeout, \"startupTimeout\"),\n );\n const abort = startupAbort(app);\n const deadline = createStartupDeadline(startupTimeoutMs, abort.signal);\n let handle;\n let phase = \"current CF target discovery\";\n let key: ResolvedSessionKey;\n try {\n key = await resolveSessionKey({ ...options, app }, deadline.signal);\n if (deadlineTimedOut(deadline)) {\n throw startupTimeoutError(startupTimeoutMs, phase);\n }\n phase = \"startup\";\n handle = await startDebuggerWithinDeadline({\n ...buildStartOptions(options, key, app, deadline.signal, startupTimeoutMs),\n verbose,\n onStatus: (status, message): void => {\n logStatus(verbose, status, message);\n },\n }, deadline);\n } catch (error: unknown) {\n const normalized = deadlineTimedOut(deadline) &&\n !(error instanceof CfDebuggerError && error.code === \"STARTUP_TIMEOUT\")\n ? startupTimeoutError(startupTimeoutMs, phase)\n : error;\n const exitCode = abort.requestedExitCode();\n if (exitCode !== undefined && typeof normalized === \"object\" && normalized !== null) {\n Reflect.set(normalized, \"cliExitCode\", exitCode);\n }\n throw normalized;\n } finally {\n deadline.dispose();\n abort.dispose();\n }\n writeReady(app, key, handle);\n await waitForHandle(app, handle);\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(signal?: AbortSignal): CurrentCfTargetReadOptions | undefined {\n const command = nodeProcess.env[\"CF_DEBUGGER_CF_BIN\"];\n if (command === undefined && signal === undefined) {\n return undefined;\n }\n return {\n ...(command === undefined ? {} : { command }),\n ...(signal === undefined ? {} : { signal }),\n };\n}\n\nasync function resolveSessionKey(\n options: StopCommandOptions,\n signal?: AbortSignal,\n): Promise<ResolvedSessionKey> {\n const app = readRequiredOption(options.app, \"--app or selector\");\n const region = optionalText(options.region);\n const org = optionalText(options.org);\n const space = optionalText(options.space);\n const nodePid = parseOptionalInteger(options.nodePid, \"nodePid\", 1);\n const instance = parseOptionalInteger(options.instance, \"instance\", 0);\n const target = resolveNodeTarget({\n ...(options.process === undefined ? {} : { process: options.process }),\n ...(instance === undefined ? {} : { instance }),\n ...(nodePid === undefined ? {} : { nodePid }),\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 ...(options.apiEndpoint === undefined ? {} : { apiEndpoint: options.apiEndpoint }),\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n };\n }\n const current = await readCurrentCfTarget(currentCfOptions(signal)).catch((error: unknown) => {\n if (\n error instanceof CfDebuggerError &&\n (error.code === \"ABORTED\" || error.code === \"STARTUP_TIMEOUT\")\n ) {\n throw error;\n }\n throw new CfDebuggerError(\n \"CF_TARGET_FAILED\",\n \"No current CF target. 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. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\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 ...(options.apiEndpoint === undefined ? {} : { apiEndpoint: options.apiEndpoint }),\n ...(target.nodePid === undefined ? {} : { nodePid: target.nodePid }),\n };\n}\n\nasync function resolveOptionalSessionKey(\n options: StopCommandOptions,\n): Promise<ResolvedSessionKey | undefined> {\n if (optionalText(options.app) === undefined) {\n if (\n optionalText(options.region) !== undefined ||\n optionalText(options.org) !== undefined ||\n optionalText(options.space) !== undefined\n ) {\n readRequiredOption(options.app, \"--app\");\n }\n return undefined;\n }\n return await resolveSessionKey(options);\n}\n\nfunction writeStopResult(result: Awaited<ReturnType<typeof stopDebugger>>): void {\n if (result === undefined) {\n return;\n }\n if (result.warning !== undefined) {\n nodeProcess.stderr.write(`[cf-debugger] warning: ${result.warning}\\n`);\n }\n if (result.pending) {\n nodeProcess.stdout.write(\n `Stop requested for session ${result.sessionId} (${result.app}, phase ${result.status}).\\n`,\n );\n } else if (result.stale) {\n nodeProcess.stdout.write(\n `Removed ${result.forced ? \"forced \" : \"\"}stale session ${result.sessionId} ` +\n `(${result.app}, port ${result.localPort.toString()}).\\n`,\n );\n } else {\n nodeProcess.stdout.write(\n `Stopped session ${result.sessionId} (${result.app}, port ${result.localPort.toString()}).\\n`,\n );\n }\n}\n\nasync function handleStop(\n selector: string | undefined,\n rawOptions: StopCommandOptions,\n command: Command,\n): Promise<void> {\n if (\n rawOptions.all === true &&\n (\n selector !== undefined ||\n STOP_SCOPE_OPTION_NAMES.some((name) => command.getOptionValueSource(name) === \"cli\")\n )\n ) {\n throw new CfDebuggerError(\n \"UNSAFE_INPUT\",\n \"--all cannot be combined with a selector, --session-id, or target selector options.\",\n );\n }\n const options = mergeSelector(selector, rawOptions);\n if (options.all === true) {\n const summary = await stopAllDebuggers(options.force === true);\n for (const outcome of summary.outcomes) {\n if (outcome.error === undefined) {\n writeStopResult(outcome.result);\n } else {\n nodeProcess.stderr.write(\n `Failed ${outcome.sessionId} (${outcome.app}): ${outcome.error.message}\\n`,\n );\n }\n }\n nodeProcess.stdout.write(\n `Stop summary: ${summary.stopped.toString()} stopped, ${summary.stale.toString()} stale, ` +\n `${summary.pending.toString()} pending, ${summary.failed.toString()} failed.\\n`,\n );\n if (summary.failed > 0) {\n nodeProcess.exitCode = 1;\n }\n return;\n }\n const key = await resolveOptionalSessionKey(options);\n const result = await stopDebugger({\n ...(options.sessionId === undefined ? {} : { sessionId: options.sessionId }),\n ...(key === undefined ? {} : { key }),\n force: options.force === true,\n });\n if (result === undefined) {\n throw new CfDebuggerError(\n \"SESSION_NOT_FOUND\",\n \"No matching session. Use `cf-debugger list` and pass --session-id or an exact key.\",\n );\n }\n writeStopResult(result);\n}\n\nasync function handleList(): Promise<void> {\n nodeProcess.stdout.write(`${JSON.stringify(await listSessions(), null, 2)}\\n`);\n}\n\nasync function handleStatus(\n selector: string | undefined,\n rawOptions: StatusCommandOptions,\n): Promise<void> {\n const options = mergeSelector(selector, rawOptions);\n const session = options.sessionId === undefined\n ? await getSession(await resolveSessionKey(options))\n : (await listSessions()).find((candidate) => candidate.sessionId === options.sessionId);\n nodeProcess.stdout.write(`${JSON.stringify(session ?? null, null, 2)}\\n`);\n}\n\nasync function handleDoctor(cleanup: boolean): Promise<void> {\n const report = await runDoctor({ cleanup });\n nodeProcess.stdout.write(`${JSON.stringify(report, 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> or <region>/<org>/<space>/<app>\")\n .option(\"--region <key>\", \"CF region key (default: current cf target)\")\n .option(\"--api-endpoint <url>\", \"Explicit CF API endpoint override\")\n .option(\"--org <name>\", \"CF org (default: current cf target)\")\n .option(\"--space <name>\", \"CF space (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\", \"0\")\n .option(\"--node-pid <pid>\", \"Explicit remote Node.js PID\")\n .option(\"--port <number>\", \"Preferred local port\")\n .option(\n \"--remote-port <number>\",\n \"Remote inspector port\",\n DEFAULT_NODE_INSPECTOR_PORT.toString(),\n )\n .option(\"--timeout <seconds>\", \"Tunnel/inspector readiness timeout\", \"180\")\n .option(\"--startup-timeout <seconds>\", \"Overall startup deadline\", \"300\")\n .option(\n \"--allow-ssh-enable-restart\",\n \"Allow app-level SSH enablement and an app restart (opt-in)\",\n )\n .option(\n \"--no-ssh-enable-restart\",\n \"Forbid app-level SSH enablement and restart, overriding flag/environment\",\n )\n .option(\"--verbose\", \"Print status transitions and tunnel diagnostics\", false)\n .action(async (selector: string | undefined, options: StartCommandOptions): Promise<void> => {\n await handleStart(selector, options);\n });\n}\n\nfunction addKeyOptions(command: Command): Command {\n return command\n .option(\"--region <key>\")\n .option(\"--api-endpoint <url>\", \"Exact API endpoint selector\")\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\", \"0\")\n .option(\"--node-pid <pid>\", \"Exact remote Node PID selector\");\n}\n\nfunction registerStopCommand(program: Command): void {\n addKeyOptions(\n program\n .command(\"stop\")\n .description(\"Stop one session by exact key/id, or every session with --all\")\n .argument(\"[selector]\", \"Optional <app> or <region>/<org>/<space>/<app>\"),\n )\n .option(\"--session-id <id>\")\n .option(\n \"--all\",\n \"Attempt every active session; cannot be combined with session selectors\",\n false,\n )\n .option(\n \"--force\",\n \"Forget unverifiable state and its owned CF home; never signal an unverified process\",\n false,\n )\n .action(\n async (\n selector: string | undefined,\n options: StopCommandOptions,\n command: Command,\n ): Promise<void> => {\n await handleStop(selector, options, command);\n },\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 addKeyOptions(\n program\n .command(\"status\")\n .description(\"Print one exact session as JSON; null only when no session matches\")\n .argument(\"[selector]\", \"Optional <app> or <region>/<org>/<space>/<app>\"),\n )\n .option(\"--session-id <id>\", \"Exact session ID selector\")\n .action(async (selector: string | undefined, options: StatusCommandOptions): Promise<void> => {\n await handleStatus(selector, options);\n });\n program\n .command(\"doctor\")\n .description(\"Report session health, orphan homes/ports, temp files, and legacy credentials\")\n .option(\"--cleanup\", \"Remove only safe orphan v2 homes and stale v2 temp/lock files\", false)\n .action(async (options: { readonly cleanup?: boolean }): Promise<void> => {\n await handleDoctor(options.cleanup === true);\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 Node.js inspector\")\n .version(packageMetadata.version);\n registerStartCommand(program);\n registerStopCommand(program);\n registerReadCommands(program);\n await program.parseAsync([...argv]);\n}\n\nfunction writeTopLevelError(error: unknown): void {\n if (error instanceof CfDebuggerError) {\n if (error.code === \"ABORTED\") {\n nodeProcess.stderr.write(`Aborted: ${error.message}\\n`);\n nodeProcess.exit(cliErrorExitCode(error));\n }\n nodeProcess.stderr.write(`Error [${error.code}]: ${error.message}\\n`);\n if (error.stderr !== undefined && error.stderr.trim().length > 0) {\n nodeProcess.stderr.write(`[cf-debugger transport]\\n${error.stderr.trim()}\\n`);\n }\n nodeProcess.exit(cliErrorExitCode(error));\n }\n if (hasTunnelTerminationFailure(error)) {\n const message = error instanceof Error ? error.message : String(error);\n nodeProcess.stderr.write(`Error during cleanup: ${message}\\n`);\n nodeProcess.exit(CLEANUP_FAILURE_EXIT_CODE);\n }\n const message = error instanceof Error ? error.message : String(error);\n nodeProcess.stderr.write(`Error: ${message}\\n`);\n nodeProcess.exit(cliErrorExitCode(error));\n}\n\ntry {\n await main(nodeProcess.argv);\n} catch (error: unknown) {\n writeTopLevelError(error);\n}\n","{\n \"name\": \"@saptools/cf-debugger\",\n \"version\": \"0.2.1\",\n \"description\": \"Open an SSH debug tunnel to a SAP BTP Cloud Foundry app's Node.js inspector — from any terminal, no IDE required.\",\n \"type\": \"module\",\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"bin\": {\n \"cf-debugger\": \"dist/cli.js\"\n },\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"eslint src tests\",\n \"test:unit\": \"vitest run --coverage\",\n \"test:e2e\": \"playwright test\"\n },\n \"keywords\": [\n \"sap\",\n \"cloud-foundry\",\n \"btp\",\n \"debug\",\n \"debugger\",\n \"ssh-tunnel\",\n \"node-inspector\",\n \"cli\",\n \"saptools\"\n ],\n \"author\": \"Dong Tran\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/dongitran/saptools.git\",\n \"directory\": \"packages/cf-debugger\"\n },\n \"homepage\": \"https://github.com/dongitran/saptools/tree/main/packages/cf-debugger#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/dongitran/saptools/issues\"\n },\n \"dependencies\": {\n \"commander\": \"^13.0.0\"\n },\n \"devDependencies\": {\n \"@playwright/test\": \"^1.50.0\",\n \"@vitest/coverage-v8\": \"^3.0.0\",\n \"tsup\": \"^8.3.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n"],"mappings":"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","names":["message"]}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED