@saptools/cf-debugger 0.2.0 → 0.2.2

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 CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  getSession,
10
10
  hasTunnelTerminationFailure,
11
11
  listSessions,
12
+ parseRestartEnvironment,
12
13
  readCurrentCfTarget,
13
14
  remainingStartupMs,
14
15
  requireCurrentCfRegion,
@@ -18,81 +19,16 @@ import {
18
19
  startDebuggerWithinDeadline,
19
20
  startupTimeoutError,
20
21
  stopAllDebuggers,
21
- stopDebugger
22
- } from "./chunk-ZWAQD7KL.js";
22
+ stopAllExitCode,
23
+ stopDebugger,
24
+ validateApiEndpointOverride
25
+ } from "./chunk-QBB4N2WN.js";
23
26
 
24
27
  // src/cli.ts
25
28
  import nodeProcess from "process";
26
29
  import { Command } from "commander";
27
30
 
28
- // package.json
29
- var package_default = {
30
- name: "@saptools/cf-debugger",
31
- version: "0.2.0",
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
- type: "module",
34
- publishConfig: {
35
- access: "public",
36
- registry: "https://registry.npmjs.org/"
37
- },
38
- bin: {
39
- "cf-debugger": "dist/cli.js"
40
- },
41
- main: "./dist/index.js",
42
- types: "./dist/index.d.ts",
43
- exports: {
44
- ".": {
45
- types: "./dist/index.d.ts",
46
- import: "./dist/index.js"
47
- }
48
- },
49
- files: [
50
- "dist"
51
- ],
52
- engines: {
53
- node: ">=20.0.0"
54
- },
55
- scripts: {
56
- build: "tsup",
57
- typecheck: "tsc --noEmit",
58
- lint: "eslint src tests",
59
- "test:unit": "vitest run --coverage",
60
- "test:e2e": "playwright test"
61
- },
62
- keywords: [
63
- "sap",
64
- "cloud-foundry",
65
- "btp",
66
- "debug",
67
- "debugger",
68
- "ssh-tunnel",
69
- "node-inspector",
70
- "cli",
71
- "saptools"
72
- ],
73
- author: "Dong Tran",
74
- license: "MIT",
75
- repository: {
76
- type: "git",
77
- url: "git+https://github.com/dongitran/saptools.git",
78
- directory: "packages/cf-debugger"
79
- },
80
- homepage: "https://github.com/dongitran/saptools/tree/main/packages/cf-debugger#readme",
81
- bugs: {
82
- url: "https://github.com/dongitran/saptools/issues"
83
- },
84
- dependencies: {
85
- commander: "^13.0.0"
86
- },
87
- devDependencies: {
88
- "@playwright/test": "^1.50.0",
89
- "@vitest/coverage-v8": "^3.0.0",
90
- tsup: "^8.3.0",
91
- vitest: "^3.0.0"
92
- }
93
- };
94
-
95
- // src/cli.ts
31
+ // src/cli-input.ts
96
32
  function readRequiredOption(value, flag) {
97
33
  if (value === void 0 || value.trim().length === 0) {
98
34
  throw new CfDebuggerError("UNSAFE_INPUT", `Missing required option ${flag}.`);
@@ -119,6 +55,24 @@ function parseSeconds(raw, label) {
119
55
  const seconds = parseOptionalInteger(raw, label, 1);
120
56
  return seconds === void 0 ? void 0 : seconds * 1e3;
121
57
  }
58
+
59
+ // src/package-version.ts
60
+ import { readFileSync } from "fs";
61
+ function readPackageVersion() {
62
+ const parsed = JSON.parse(
63
+ readFileSync(new URL("../package.json", import.meta.url), "utf8")
64
+ );
65
+ if (typeof parsed !== "object" || parsed === null) {
66
+ throw new CfDebuggerError("PACKAGE_METADATA_INVALID", "Package metadata is not an object.");
67
+ }
68
+ const version = Reflect.get(parsed, "version");
69
+ if (typeof version !== "string" || version.length === 0) {
70
+ throw new CfDebuggerError("PACKAGE_METADATA_INVALID", "Package metadata has no version.");
71
+ }
72
+ return version;
73
+ }
74
+
75
+ // src/cli.ts
122
76
  var STOP_SCOPE_OPTION_NAMES = [
123
77
  "apiEndpoint",
124
78
  "app",
@@ -244,28 +198,14 @@ ${tunnelError.stderr.trim()}
244
198
  }
245
199
  nodeProcess.exit(requestedExitCode ?? code ?? 0);
246
200
  }
247
- function parseRestartEnvironment() {
248
- const value = nodeProcess.env["CF_DEBUGGER_ALLOW_RESTART"];
249
- if (value === void 0) {
250
- return "unset";
251
- }
252
- if (value === "0") {
253
- return "forbid";
254
- }
255
- if (value === "1") {
256
- return "allow";
257
- }
258
- throw new CfDebuggerError(
259
- "UNSAFE_INPUT",
260
- "CF_DEBUGGER_ALLOW_RESTART must be 0 or 1."
261
- );
262
- }
263
201
  function buildStartOptions(options, key, app, signal, startupTimeoutMs) {
264
202
  const preferredPort = parseOptionalInteger(options.port, "port", 1, 65535);
265
203
  const remotePort = parseOptionalInteger(options.remotePort, "remotePort", 1, 65535);
266
204
  const nodePid = parseOptionalInteger(options.nodePid, "nodePid", 1);
267
205
  const tunnelReadyTimeoutMs = parseSeconds(options.timeout, "timeout");
268
- const restartEnvironment = parseRestartEnvironment();
206
+ const restartEnvironment = parseRestartEnvironment(
207
+ nodeProcess.env["CF_DEBUGGER_ALLOW_RESTART"]
208
+ );
269
209
  const allowSshEnableRestart = options.sshEnableRestart !== false && restartEnvironment !== "forbid" && (options.allowSshEnableRestart === true || restartEnvironment === "allow");
270
210
  return {
271
211
  region: key.region,
@@ -287,8 +227,14 @@ function buildStartOptions(options, key, app, signal, startupTimeoutMs) {
287
227
  function deadlineTimedOut(deadline) {
288
228
  return remainingStartupMs(deadline.expiresAt) === 0 || deadline.signal.reason instanceof CfDebuggerError && deadline.signal.reason.code === "STARTUP_TIMEOUT";
289
229
  }
230
+ function validateStartEndpoint(options) {
231
+ return options.apiEndpoint === void 0 ? options : {
232
+ ...options,
233
+ apiEndpoint: validateApiEndpointOverride(options.apiEndpoint)
234
+ };
235
+ }
290
236
  async function handleStart(selector, rawOptions) {
291
- const options = mergeSelector(selector, rawOptions);
237
+ const options = validateStartEndpoint(mergeSelector(selector, rawOptions));
292
238
  const app = readRequiredOption(options.app, "--app or selector");
293
239
  const verbose = options.verbose ?? false;
294
240
  const startupTimeoutMs = resolveStartupTimeoutMs(
@@ -340,6 +286,38 @@ function currentCfOptions(signal) {
340
286
  ...signal === void 0 ? {} : { signal }
341
287
  };
342
288
  }
289
+ function currentTargetReadError(error) {
290
+ return new CfDebuggerError(
291
+ "CF_TARGET_FAILED",
292
+ "No current CF target. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.",
293
+ error instanceof Error ? error.message : String(error)
294
+ );
295
+ }
296
+ function missingCurrentTargetError() {
297
+ return new CfDebuggerError(
298
+ "CF_TARGET_FAILED",
299
+ "No current CF target. Run `cf target -o <org> -s <space>` or pass --region/--org/--space."
300
+ );
301
+ }
302
+ async function resolveCfScope(region, org, space, signal) {
303
+ if (region !== void 0 && org !== void 0 && space !== void 0) {
304
+ return { region, org, space };
305
+ }
306
+ const current = await readCurrentCfTarget(currentCfOptions(signal)).catch((error) => {
307
+ if (error instanceof CfDebuggerError && (error.code === "ABORTED" || error.code === "STARTUP_TIMEOUT")) {
308
+ throw error;
309
+ }
310
+ throw currentTargetReadError(error);
311
+ });
312
+ if (current === void 0) {
313
+ throw missingCurrentTargetError();
314
+ }
315
+ return {
316
+ region: region ?? requireCurrentCfRegion(current),
317
+ org: org ?? current.org,
318
+ space: space ?? current.space
319
+ };
320
+ }
343
321
  async function resolveSessionKey(options, signal) {
344
322
  const app = readRequiredOption(options.app, "--app or selector");
345
323
  const region = optionalText(options.region);
@@ -352,38 +330,9 @@ async function resolveSessionKey(options, signal) {
352
330
  ...instance === void 0 ? {} : { instance },
353
331
  ...nodePid === void 0 ? {} : { nodePid }
354
332
  });
355
- if (region !== void 0 && org !== void 0 && space !== void 0) {
356
- return {
357
- region,
358
- org,
359
- space,
360
- app,
361
- process: target.process,
362
- instance: target.instance,
363
- ...options.apiEndpoint === void 0 ? {} : { apiEndpoint: options.apiEndpoint },
364
- ...target.nodePid === void 0 ? {} : { nodePid: target.nodePid }
365
- };
366
- }
367
- const current = await readCurrentCfTarget(currentCfOptions(signal)).catch((error) => {
368
- if (error instanceof CfDebuggerError && (error.code === "ABORTED" || error.code === "STARTUP_TIMEOUT")) {
369
- throw error;
370
- }
371
- throw new CfDebuggerError(
372
- "CF_TARGET_FAILED",
373
- "No current CF target. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.",
374
- error instanceof Error ? error.message : String(error)
375
- );
376
- });
377
- if (current === void 0) {
378
- throw new CfDebuggerError(
379
- "CF_TARGET_FAILED",
380
- "No current CF target. Run `cf target -o <org> -s <space>` or pass --region/--org/--space."
381
- );
382
- }
333
+ const scope = await resolveCfScope(region, org, space, signal);
383
334
  return {
384
- region: region ?? requireCurrentCfRegion(current),
385
- org: org ?? current.org,
386
- space: space ?? current.space,
335
+ ...scope,
387
336
  app,
388
337
  process: target.process,
389
338
  instance: target.instance,
@@ -394,7 +343,7 @@ async function resolveSessionKey(options, signal) {
394
343
  async function resolveOptionalSessionKey(options) {
395
344
  if (optionalText(options.app) === void 0) {
396
345
  if (optionalText(options.region) !== void 0 || optionalText(options.org) !== void 0 || optionalText(options.space) !== void 0) {
397
- readRequiredOption(options.app, "--app");
346
+ readRequiredOption(options.app, "--app or selector");
398
347
  }
399
348
  return void 0;
400
349
  }
@@ -425,33 +374,42 @@ function writeStopResult(result) {
425
374
  );
426
375
  }
427
376
  }
428
- async function handleStop(selector, rawOptions, command) {
429
- if (rawOptions.all === true && (selector !== void 0 || STOP_SCOPE_OPTION_NAMES.some((name) => command.getOptionValueSource(name) === "cli"))) {
377
+ function rejectScopedStopAll(selector, options, command) {
378
+ if (options.all === true && (selector !== void 0 || STOP_SCOPE_OPTION_NAMES.some((name) => command.getOptionValueSource(name) === "cli"))) {
430
379
  throw new CfDebuggerError(
431
380
  "UNSAFE_INPUT",
432
381
  "--all cannot be combined with a selector, --session-id, or target selector options."
433
382
  );
434
383
  }
435
- const options = mergeSelector(selector, rawOptions);
436
- if (options.all === true) {
437
- const summary = await stopAllDebuggers(options.force === true);
438
- for (const outcome of summary.outcomes) {
439
- if (outcome.error === void 0) {
440
- writeStopResult(outcome.result);
441
- } else {
442
- nodeProcess.stderr.write(
443
- `Failed ${outcome.sessionId} (${outcome.app}): ${outcome.error.message}
384
+ }
385
+ async function handleStopAll(force) {
386
+ const summary = await stopAllDebuggers(force);
387
+ for (const outcome of summary.outcomes) {
388
+ if (outcome.error === void 0) {
389
+ writeStopResult(outcome.result);
390
+ } else {
391
+ nodeProcess.stderr.write(
392
+ `Failed ${outcome.sessionId} (${outcome.app}): ${outcome.error.message}
444
393
  `
445
- );
446
- }
394
+ );
447
395
  }
448
- nodeProcess.stdout.write(
449
- `Stop summary: ${summary.stopped.toString()} stopped, ${summary.stale.toString()} stale, ${summary.pending.toString()} pending, ${summary.failed.toString()} failed.
396
+ }
397
+ nodeProcess.stdout.write(
398
+ `Stop summary: ${summary.stopped.toString()} stopped, ${summary.forced.toString()} forced, ${summary.stale.toString()} stale, ${summary.pending.toString()} pending, ${summary.failed.toString()} failed.
450
399
  `
451
- );
452
- if (summary.failed > 0) {
453
- nodeProcess.exitCode = 1;
454
- }
400
+ );
401
+ const exitCode = stopAllExitCode(
402
+ summary.outcomes.flatMap((outcome) => outcome.error === void 0 ? [] : [outcome.error])
403
+ );
404
+ if (exitCode !== void 0) {
405
+ nodeProcess.exitCode = exitCode;
406
+ }
407
+ }
408
+ async function handleStop(selector, rawOptions, command) {
409
+ rejectScopedStopAll(selector, rawOptions, command);
410
+ const options = mergeSelector(selector, rawOptions);
411
+ if (options.all === true) {
412
+ await handleStopAll(options.force === true);
455
413
  return;
456
414
  }
457
415
  const key = await resolveOptionalSessionKey(options);
@@ -484,9 +442,9 @@ async function handleDoctor(cleanup) {
484
442
  `);
485
443
  }
486
444
  function registerStartCommand(program) {
487
- program.command("start").description("Open a debug tunnel for one app").argument("[selector]", "Optional <app> or <region>/<org>/<space>/<app>").option("--region <key>", "CF region key (default: current cf target)").option("--api-endpoint <url>", "Explicit CF API endpoint override").option("--org <name>", "CF org (default: current cf target)").option("--space <name>", "CF space (default: current cf target)").option("--app <name>", "CF app name").option("--process <name>", "CF process name", "web").option("-i, --instance <index>", "CF process instance", "0").option("--node-pid <pid>", "Explicit remote Node.js PID").option("--port <number>", "Preferred local port").option(
445
+ program.command("start").description("Open a debug tunnel for one app").argument("[selector]", "Optional <app> or <region>/<org>/<space>/<app>").option("--region <key>", "CF region key (default: current cf target)").option("--api-endpoint <url>", "Absolute HTTPS CF API endpoint override").option("--org <name>", "CF org (default: current cf target)").option("--space <name>", "CF space (default: current cf target)").option("--app <name>", "CF app name").option("--process <name>", "CF process name", "web").option("-i, --instance <index>", "CF process instance", "0").option("--node-pid <pid>", "Explicit remote Node.js PID").option("--port <number>", "Preferred local port").option(
488
446
  "--remote-port <number>",
489
- "Remote inspector port",
447
+ "Port where cf-debugger looks for an existing remote inspector",
490
448
  DEFAULT_NODE_INSPECTOR_PORT.toString()
491
449
  ).option("--timeout <seconds>", "Tunnel/inspector readiness timeout", "180").option("--startup-timeout <seconds>", "Overall startup deadline", "300").option(
492
450
  "--allow-ssh-enable-restart",
@@ -510,7 +468,7 @@ function registerStopCommand(program) {
510
468
  false
511
469
  ).option(
512
470
  "--force",
513
- "Forget unverifiable state and its owned CF home; never signal an unverified process",
471
+ "Forget unverifiable state first; best-effort remove its exact owned CF home; never signal an unverified process",
514
472
  false
515
473
  ).action(
516
474
  async (selector, options, command) => {
@@ -532,7 +490,7 @@ function registerReadCommands(program) {
532
490
  });
533
491
  }
534
492
  async function main(argv) {
535
- const program = new Command().name("cf-debugger").description("Open an SSH debug tunnel to a SAP BTP Cloud Foundry Node.js inspector").version(package_default.version);
493
+ const program = new Command().name("cf-debugger").description("Open an SSH debug tunnel to a SAP BTP Cloud Foundry Node.js inspector").version(readPackageVersion());
536
494
  registerStartCommand(program);
537
495
  registerStopCommand(program);
538
496
  registerReadCommands(program);
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","../src/cli-input.ts","../src/package-version.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport nodeProcess from \"node:process\";\n\nimport { Command } from \"commander\";\n\nimport { readCurrentCfTarget, requireCurrentCfRegion } from \"./cf.js\";\nimport type { CurrentCfTargetReadOptions } from \"./cf.js\";\nimport {\n CLEANUP_FAILURE_EXIT_CODE,\n cliErrorExitCode,\n hasTunnelTerminationFailure,\n stopAllExitCode,\n} from \"./cli-errors.js\";\nimport {\n parseOptionalInteger,\n parseSeconds,\n readRequiredOption,\n} from \"./cli-input.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 { readPackageVersion } from \"./package-version.js\";\nimport { validateApiEndpointOverride } from \"./regions.js\";\nimport { parseRestartEnvironment } from \"./restart-policy.js\";\nimport type {\n DebuggerHandle,\n ResolvedSessionKey,\n SessionStatus,\n StartDebuggerOptions,\n} from \"./types.js\";\nimport { CfDebuggerError } from \"./types.js\";\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\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 nodeProcess.env[\"CF_DEBUGGER_ALLOW_RESTART\"],\n );\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\nfunction validateStartEndpoint(options: StartCommandOptions): StartCommandOptions {\n return options.apiEndpoint === undefined\n ? options\n : {\n ...options,\n apiEndpoint: validateApiEndpointOverride(options.apiEndpoint),\n };\n}\n\nasync function handleStart(\n selector: string | undefined,\n rawOptions: StartCommandOptions,\n): Promise<void> {\n const options = validateStartEndpoint(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\ninterface ResolvedCfScope {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n}\n\nfunction currentTargetReadError(error: unknown): CfDebuggerError {\n return 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\nfunction missingCurrentTargetError(): CfDebuggerError {\n return 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\nasync function resolveCfScope(\n region: string | undefined,\n org: string | undefined,\n space: string | undefined,\n signal?: AbortSignal,\n): Promise<ResolvedCfScope> {\n if (region !== undefined && org !== undefined && space !== undefined) {\n return { region, org, space };\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 currentTargetReadError(error);\n });\n if (current === undefined) {\n throw missingCurrentTargetError();\n }\n return {\n region: region ?? requireCurrentCfRegion(current),\n org: org ?? current.org,\n space: space ?? current.space,\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 const scope = await resolveCfScope(region, org, space, signal);\n return {\n ...scope,\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 or selector\");\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\nfunction rejectScopedStopAll(\n selector: string | undefined,\n options: StopCommandOptions,\n command: Command,\n): void {\n if (\n options.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}\n\nasync function handleStopAll(force: boolean): Promise<void> {\n const summary = await stopAllDebuggers(force);\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.forced.toString()} forced, ` +\n `${summary.stale.toString()} stale, ` +\n `${summary.pending.toString()} pending, ${summary.failed.toString()} failed.\\n`,\n );\n const exitCode = stopAllExitCode(\n summary.outcomes.flatMap((outcome) =>\n outcome.error === undefined ? [] : [outcome.error]),\n );\n if (exitCode !== undefined) {\n nodeProcess.exitCode = exitCode;\n }\n}\n\nasync function handleStop(\n selector: string | undefined,\n rawOptions: StopCommandOptions,\n command: Command,\n): Promise<void> {\n rejectScopedStopAll(selector, rawOptions, command);\n const options = mergeSelector(selector, rawOptions);\n if (options.all === true) {\n await handleStopAll(options.force === true);\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>\", \"Absolute HTTPS 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 \"Port where cf-debugger looks for an existing remote inspector\",\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 first; best-effort remove its exact owned CF home; \" +\n \"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(readPackageVersion());\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","import { CfDebuggerError } from \"./types.js\";\n\nexport function readRequiredOption(\n value: string | undefined,\n flag: string,\n): 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\nexport function 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\nexport function parseSeconds(\n raw: string | undefined,\n label: string,\n): number | undefined {\n const seconds = parseOptionalInteger(raw, label, 1);\n return seconds === undefined ? undefined : seconds * 1000;\n}\n","import { readFileSync } from \"node:fs\";\n\nimport { CfDebuggerError } from \"./types.js\";\n\nexport function readPackageVersion(): string {\n const parsed: unknown = JSON.parse(\n readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n );\n if (typeof parsed !== \"object\" || parsed === null) {\n throw new CfDebuggerError(\"PACKAGE_METADATA_INVALID\", \"Package metadata is not an object.\");\n }\n const version: unknown = Reflect.get(parsed, \"version\");\n if (typeof version !== \"string\" || version.length === 0) {\n throw new CfDebuggerError(\"PACKAGE_METADATA_INVALID\", \"Package metadata has no version.\");\n }\n return version;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,OAAO,iBAAiB;AAExB,SAAS,eAAe;;;ACFjB,SAAS,mBACd,OACA,MACQ;AACR,MAAI,UAAU,UAAa,MAAM,KAAK,EAAE,WAAW,GAAG;AACpD,UAAM,IAAI,gBAAgB,gBAAgB,2BAA2B,IAAI,GAAG;AAAA,EAC9E;AACA,SAAO;AACT;AAEO,SAAS,qBACd,KACA,OACA,SACA,UAAU,OAAO,kBACG;AACpB,MAAI,QAAQ,QAAW;AACrB,WAAO;AAAA,EACT;AACA,MAAI,CAAC,QAAQ,KAAK,GAAG,GAAG;AACtB,UAAM,IAAI,gBAAgB,gBAAgB,GAAG,KAAK,sBAAsB;AAAA,EAC1E;AACA,QAAM,QAAQ,OAAO,GAAG;AACxB,MAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,WAAW,QAAQ,SAAS;AACtE,UAAM,IAAI;AAAA,MACR;AAAA,MACA,GAAG,KAAK,iBAAiB,QAAQ,SAAS,CAAC,OAAO,QAAQ,SAAS,CAAC;AAAA,IACtE;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,aACd,KACA,OACoB;AACpB,QAAM,UAAU,qBAAqB,KAAK,OAAO,CAAC;AAClD,SAAO,YAAY,SAAY,SAAY,UAAU;AACvD;;;ACxCA,SAAS,oBAAoB;AAItB,SAAS,qBAA6B;AAC3C,QAAM,SAAkB,KAAK;AAAA,IAC3B,aAAa,IAAI,IAAI,mBAAmB,YAAY,GAAG,GAAG,MAAM;AAAA,EAClE;AACA,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,UAAM,IAAI,gBAAgB,4BAA4B,oCAAoC;AAAA,EAC5F;AACA,QAAM,UAAmB,QAAQ,IAAI,QAAQ,SAAS;AACtD,MAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,GAAG;AACvD,UAAM,IAAI,gBAAgB,4BAA4B,kCAAkC;AAAA,EAC1F;AACA,SAAO;AACT;;;AFiEA,IAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,UAAU,SAAkB,QAAuB,SAAwB;AAClF,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AACA,QAAM,SAAS,YAAY,SAAY,KAAK,KAAK,OAAO;AACxD,cAAY,OAAO,MAAM,iBAAiB,MAAM,GAAG,MAAM;AAAA,CAAI;AAC/D;AAEA,SAAS,cAEP,UAA8B,SAAe;AAC7C,MAAI,aAAa,QAAW;AAC1B,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,SAAS,MAAM,GAAG;AAChC,MAAI,MAAM,WAAW,KAAK,MAAM,CAAC,GAAG,WAAW,GAAG;AAChD,WAAO,EAAE,GAAG,SAAS,KAAK,QAAQ,OAAO,MAAM,CAAC,EAAE;AAAA,EACpD;AACA,MAAI,MAAM,WAAW,KAAK,MAAM,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,GAAG;AAChE,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ,QAAQ,UAAU,MAAM,CAAC;AAAA,MACjC,KAAK,QAAQ,OAAO,MAAM,CAAC;AAAA,MAC3B,OAAO,QAAQ,SAAS,MAAM,CAAC;AAAA,MAC/B,KAAK,QAAQ,OAAO,MAAM,CAAC;AAAA,IAC7B;AAAA,EACF;AACA,QAAM,IAAI;AAAA,IACR;AAAA,IACA;AAAA,EACF;AACF;AAQA,SAAS,aAAa,KAA2B;AAC/C,QAAM,aAAa,IAAI,gBAAgB;AACvC,MAAI;AACJ,QAAM,UAAU,CAAC,aAAqB,MAAY;AAChD,0BAAsB;AACtB,eAAW,MAAM;AACjB,gBAAY,OAAO,MAAM;AAAA,uBAA0B,GAAG;AAAA,CAAO;AAAA,EAC/D;AACA,QAAM,WAAW,QAAQ,GAAG;AAC5B,QAAM,YAAY,QAAQ,GAAG;AAC7B,cAAY,GAAG,UAAU,QAAQ;AACjC,cAAY,GAAG,WAAW,SAAS;AACnC,SAAO;AAAA,IACL,QAAQ,WAAW;AAAA,IACnB,mBAAmB,MAA0B;AAAA,IAC7C,SAAS,MAAY;AACnB,kBAAY,IAAI,UAAU,QAAQ;AAClC,kBAAY,IAAI,WAAW,SAAS;AAAA,IACtC;AAAA,EACF;AACF;AAEA,SAAS,WACP,KACA,KACA,QACM;AACN,cAAY,OAAO;AAAA,IACjB,sBAAsB,GAAG,KAAK,IAAI,MAAM,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;AAAA,iBAC5C,IAAI,OAAO;AAAA,iBACX,IAAI,SAAS,SAAS,CAAC;AAAA,iBACvB,OAAO,QAAQ,UAAU,SAAS,CAAC;AAAA,iBACnC,OAAO,QAAQ,WAAW,SAAS,CAAC;AAAA,iBACpC,OAAO,QAAQ,SAAS;AAAA,iBACxB,OAAO,QAAQ,IAAI,SAAS,CAAC;AAAA,iBAC7B,OAAO,QAAQ,eAAe,SAAS,KAAK,SAAS;AAAA;AAAA;AAAA,EAE3E;AACF;AAEA,SAAS,kBAAkB,OAAsB;AAC/C,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAY,OAAO,MAAM,sBAAsB,OAAO;AAAA,CAAI;AAC5D;AAEA,eAAe,cACb,KACA,QACe;AACf,MAAI;AACJ,MAAI;AACJ,QAAM,UAAU,MAAqB;AACnC,wBAAoB,YAA2B;AAC7C,kBAAY,OAAO,MAAM;AAAA,wBAA2B,GAAG;AAAA,CAAO;AAC9D,YAAM,OAAO,QAAQ;AAAA,IACvB,GAAG;AACH,WAAO;AAAA,EACT;AACA,QAAM,OAAO,CAAC,aAAqB,MAAY;AAC7C,wBAAoB;AACpB,SAAK,QAAQ,EACV,MAAM,CAAC,UAAmB;AACzB,wBAAkB,KAAK;AACvB,kBAAY,KAAK,yBAAyB;AAAA,IAC5C,CAAC;AAAA,EACL;AACA,cAAY,GAAG,UAAU,KAAK,GAAG,CAAC;AAClC,cAAY,GAAG,WAAW,KAAK,GAAG,CAAC;AACnC,QAAM,OAAO,MAAM,OAAO,YAAY;AACtC,QAAM,cAAc,6BAA6B,MAAM;AACvD,MAAI,gBAAgB,QAAW;AAC7B,gBAAY,OAAO;AAAA,MACjB,UAAU,YAAY,IAAI,MAAM,YAAY,OAAO;AAAA;AAAA,IACrD;AACA,QAAI,YAAY,WAAW,UAAa,YAAY,OAAO,KAAK,EAAE,SAAS,GAAG;AAC5E,kBAAY,OAAO,MAAM;AAAA,EAA4B,YAAY,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,IACpF;AAAA,EACF;AACA,MAAI;AACF,UAAM,QAAQ;AAAA,EAChB,SAAS,OAAgB;AACvB,sBAAkB,KAAK;AACvB,gBAAY,KAAK,yBAAyB;AAAA,EAC5C;AACA,cAAY,KAAK,qBAAqB,QAAQ,CAAC;AACjD;AAEA,SAAS,kBACP,SACA,KACA,KACA,QACA,kBACsB;AACtB,QAAM,gBAAgB,qBAAqB,QAAQ,MAAM,QAAQ,GAAG,KAAM;AAC1E,QAAM,aAAa,qBAAqB,QAAQ,YAAY,cAAc,GAAG,KAAM;AACnF,QAAM,UAAU,qBAAqB,QAAQ,SAAS,WAAW,CAAC;AAClE,QAAM,uBAAuB,aAAa,QAAQ,SAAS,SAAS;AACpE,QAAM,qBAAqB;AAAA,IACzB,YAAY,IAAI,2BAA2B;AAAA,EAC7C;AACA,QAAM,wBACJ,QAAQ,qBAAqB,SAC7B,uBAAuB,aACtB,QAAQ,0BAA0B,QAAQ,uBAAuB;AACpE,SAAO;AAAA,IACL,QAAQ,IAAI;AAAA,IACZ,KAAK,IAAI;AAAA,IACT,OAAO,IAAI;AAAA,IACX;AAAA,IACA,SAAS,IAAI;AAAA,IACb,UAAU,IAAI;AAAA,IACd;AAAA,IACA;AAAA,IACA,GAAI,QAAQ,gBAAgB,SAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;AAAA,IAChF,GAAI,kBAAkB,SAAY,CAAC,IAAI,EAAE,cAAc;AAAA,IACvD,GAAI,eAAe,SAAY,CAAC,IAAI,EAAE,WAAW;AAAA,IACjD,GAAI,YAAY,SAAY,CAAC,IAAI,EAAE,QAAQ;AAAA,IAC3C,GAAI,yBAAyB,SAAY,CAAC,IAAI,EAAE,qBAAqB;AAAA,IACrE;AAAA,EACF;AACF;AAEA,SAAS,iBACP,UACS;AACT,SAAO,mBAAmB,SAAS,SAAS,MAAM,KAE9C,SAAS,OAAO,kBAAkB,mBAClC,SAAS,OAAO,OAAO,SAAS;AAEtC;AAEA,SAAS,sBAAsB,SAAmD;AAChF,SAAO,QAAQ,gBAAgB,SAC3B,UACA;AAAA,IACE,GAAG;AAAA,IACH,aAAa,4BAA4B,QAAQ,WAAW;AAAA,EAC9D;AACN;AAEA,eAAe,YACb,UACA,YACe;AACf,QAAM,UAAU,sBAAsB,cAAc,UAAU,UAAU,CAAC;AACzE,QAAM,MAAM,mBAAmB,QAAQ,KAAK,mBAAmB;AAC/D,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,mBAAmB;AAAA,IACvB,aAAa,QAAQ,gBAAgB,gBAAgB;AAAA,EACvD;AACA,QAAM,QAAQ,aAAa,GAAG;AAC9B,QAAM,WAAW,sBAAsB,kBAAkB,MAAM,MAAM;AACrE,MAAI;AACJ,MAAI,QAAQ;AACZ,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,kBAAkB,EAAE,GAAG,SAAS,IAAI,GAAG,SAAS,MAAM;AAClE,QAAI,iBAAiB,QAAQ,GAAG;AAC9B,YAAM,oBAAoB,kBAAkB,KAAK;AAAA,IACnD;AACA,YAAQ;AACR,aAAS,MAAM,4BAA4B;AAAA,MACzC,GAAG,kBAAkB,SAAS,KAAK,KAAK,SAAS,QAAQ,gBAAgB;AAAA,MACzE;AAAA,MACA,UAAU,CAAC,QAAQ,YAAkB;AACnC,kBAAU,SAAS,QAAQ,OAAO;AAAA,MACpC;AAAA,IACF,GAAG,QAAQ;AAAA,EACb,SAAS,OAAgB;AACvB,UAAM,aAAa,iBAAiB,QAAQ,KAC1C,EAAE,iBAAiB,mBAAmB,MAAM,SAAS,qBACnD,oBAAoB,kBAAkB,KAAK,IAC3C;AACJ,UAAM,WAAW,MAAM,kBAAkB;AACzC,QAAI,aAAa,UAAa,OAAO,eAAe,YAAY,eAAe,MAAM;AACnF,cAAQ,IAAI,YAAY,eAAe,QAAQ;AAAA,IACjD;AACA,UAAM;AAAA,EACR,UAAE;AACA,aAAS,QAAQ;AACjB,UAAM,QAAQ;AAAA,EAChB;AACA,aAAW,KAAK,KAAK,MAAM;AAC3B,QAAM,cAAc,KAAK,MAAM;AACjC;AAEA,SAAS,aAAa,OAA+C;AACnE,QAAM,UAAU,OAAO,KAAK;AAC5B,SAAO,YAAY,UAAa,QAAQ,WAAW,IAAI,SAAY;AACrE;AAEA,SAAS,iBAAiB,QAA8D;AACtF,QAAM,UAAU,YAAY,IAAI,oBAAoB;AACpD,MAAI,YAAY,UAAa,WAAW,QAAW;AACjD,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,GAAI,YAAY,SAAY,CAAC,IAAI,EAAE,QAAQ;AAAA,IAC3C,GAAI,WAAW,SAAY,CAAC,IAAI,EAAE,OAAO;AAAA,EAC3C;AACF;AAQA,SAAS,uBAAuB,OAAiC;AAC/D,SAAO,IAAI;AAAA,IACT;AAAA,IACA;AAAA,IACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,EACvD;AACF;AAEA,SAAS,4BAA6C;AACpD,SAAO,IAAI;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,eACb,QACA,KACA,OACA,QAC0B;AAC1B,MAAI,WAAW,UAAa,QAAQ,UAAa,UAAU,QAAW;AACpE,WAAO,EAAE,QAAQ,KAAK,MAAM;AAAA,EAC9B;AACA,QAAM,UAAU,MAAM,oBAAoB,iBAAiB,MAAM,CAAC,EAAE,MAAM,CAAC,UAAmB;AAC5F,QACE,iBAAiB,oBAChB,MAAM,SAAS,aAAa,MAAM,SAAS,oBAC5C;AACA,YAAM;AAAA,IACR;AACA,UAAM,uBAAuB,KAAK;AAAA,EACpC,CAAC;AACD,MAAI,YAAY,QAAW;AACzB,UAAM,0BAA0B;AAAA,EAClC;AACA,SAAO;AAAA,IACL,QAAQ,UAAU,uBAAuB,OAAO;AAAA,IAChD,KAAK,OAAO,QAAQ;AAAA,IACpB,OAAO,SAAS,QAAQ;AAAA,EAC1B;AACF;AAEA,eAAe,kBACb,SACA,QAC6B;AAC7B,QAAM,MAAM,mBAAmB,QAAQ,KAAK,mBAAmB;AAC/D,QAAM,SAAS,aAAa,QAAQ,MAAM;AAC1C,QAAM,MAAM,aAAa,QAAQ,GAAG;AACpC,QAAM,QAAQ,aAAa,QAAQ,KAAK;AACxC,QAAM,UAAU,qBAAqB,QAAQ,SAAS,WAAW,CAAC;AAClE,QAAM,WAAW,qBAAqB,QAAQ,UAAU,YAAY,CAAC;AACrE,QAAM,SAAS,kBAAkB;AAAA,IAC/B,GAAI,QAAQ,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;AAAA,IACpE,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,IAC7C,GAAI,YAAY,SAAY,CAAC,IAAI,EAAE,QAAQ;AAAA,EAC7C,CAAC;AACD,QAAM,QAAQ,MAAM,eAAe,QAAQ,KAAK,OAAO,MAAM;AAC7D,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,SAAS,OAAO;AAAA,IAChB,UAAU,OAAO;AAAA,IACjB,GAAI,QAAQ,gBAAgB,SAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;AAAA,IAChF,GAAI,OAAO,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,OAAO,QAAQ;AAAA,EACpE;AACF;AAEA,eAAe,0BACb,SACyC;AACzC,MAAI,aAAa,QAAQ,GAAG,MAAM,QAAW;AAC3C,QACE,aAAa,QAAQ,MAAM,MAAM,UACjC,aAAa,QAAQ,GAAG,MAAM,UAC9B,aAAa,QAAQ,KAAK,MAAM,QAChC;AACA,yBAAmB,QAAQ,KAAK,mBAAmB;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AACA,SAAO,MAAM,kBAAkB,OAAO;AACxC;AAEA,SAAS,gBAAgB,QAAwD;AAC/E,MAAI,WAAW,QAAW;AACxB;AAAA,EACF;AACA,MAAI,OAAO,YAAY,QAAW;AAChC,gBAAY,OAAO,MAAM,0BAA0B,OAAO,OAAO;AAAA,CAAI;AAAA,EACvE;AACA,MAAI,OAAO,SAAS;AAClB,gBAAY,OAAO;AAAA,MACjB,8BAA8B,OAAO,SAAS,KAAK,OAAO,GAAG,WAAW,OAAO,MAAM;AAAA;AAAA,IACvF;AAAA,EACF,WAAW,OAAO,OAAO;AACvB,gBAAY,OAAO;AAAA,MACjB,WAAW,OAAO,SAAS,YAAY,EAAE,iBAAiB,OAAO,SAAS,KACpE,OAAO,GAAG,UAAU,OAAO,UAAU,SAAS,CAAC;AAAA;AAAA,IACvD;AAAA,EACF,OAAO;AACL,gBAAY,OAAO;AAAA,MACjB,mBAAmB,OAAO,SAAS,KAAK,OAAO,GAAG,UAAU,OAAO,UAAU,SAAS,CAAC;AAAA;AAAA,IACzF;AAAA,EACF;AACF;AAEA,SAAS,oBACP,UACA,SACA,SACM;AACN,MACE,QAAQ,QAAQ,SAEd,aAAa,UACb,wBAAwB,KAAK,CAAC,SAAS,QAAQ,qBAAqB,IAAI,MAAM,KAAK,IAErF;AACA,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,cAAc,OAA+B;AAC1D,QAAM,UAAU,MAAM,iBAAiB,KAAK;AAC5C,aAAW,WAAW,QAAQ,UAAU;AACtC,QAAI,QAAQ,UAAU,QAAW;AAC/B,sBAAgB,QAAQ,MAAM;AAAA,IAChC,OAAO;AACL,kBAAY,OAAO;AAAA,QACjB,UAAU,QAAQ,SAAS,KAAK,QAAQ,GAAG,MAAM,QAAQ,MAAM,OAAO;AAAA;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AACA,cAAY,OAAO;AAAA,IACjB,iBAAiB,QAAQ,QAAQ,SAAS,CAAC,aAAa,QAAQ,OAAO,SAAS,CAAC,YAC5E,QAAQ,MAAM,SAAS,CAAC,WACxB,QAAQ,QAAQ,SAAS,CAAC,aAAa,QAAQ,OAAO,SAAS,CAAC;AAAA;AAAA,EACvE;AACA,QAAM,WAAW;AAAA,IACf,QAAQ,SAAS,QAAQ,CAAC,YACxB,QAAQ,UAAU,SAAY,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC;AAAA,EACtD;AACA,MAAI,aAAa,QAAW;AAC1B,gBAAY,WAAW;AAAA,EACzB;AACF;AAEA,eAAe,WACb,UACA,YACA,SACe;AACf,sBAAoB,UAAU,YAAY,OAAO;AACjD,QAAM,UAAU,cAAc,UAAU,UAAU;AAClD,MAAI,QAAQ,QAAQ,MAAM;AACxB,UAAM,cAAc,QAAQ,UAAU,IAAI;AAC1C;AAAA,EACF;AACA,QAAM,MAAM,MAAM,0BAA0B,OAAO;AACnD,QAAM,SAAS,MAAM,aAAa;AAAA,IAChC,GAAI,QAAQ,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;AAAA,IAC1E,GAAI,QAAQ,SAAY,CAAC,IAAI,EAAE,IAAI;AAAA,IACnC,OAAO,QAAQ,UAAU;AAAA,EAC3B,CAAC;AACD,MAAI,WAAW,QAAW;AACxB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,kBAAgB,MAAM;AACxB;AAEA,eAAe,aAA4B;AACzC,cAAY,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC;AAAA,CAAI;AAC/E;AAEA,eAAe,aACb,UACA,YACe;AACf,QAAM,UAAU,cAAc,UAAU,UAAU;AAClD,QAAM,UAAU,QAAQ,cAAc,SAClC,MAAM,WAAW,MAAM,kBAAkB,OAAO,CAAC,KAChD,MAAM,aAAa,GAAG,KAAK,CAAC,cAAc,UAAU,cAAc,QAAQ,SAAS;AACxF,cAAY,OAAO,MAAM,GAAG,KAAK,UAAU,WAAW,MAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AAC1E;AAEA,eAAe,aAAa,SAAiC;AAC3D,QAAM,SAAS,MAAM,UAAU,EAAE,QAAQ,CAAC;AAC1C,cAAY,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AACjE;AAEA,SAAS,qBAAqB,SAAwB;AACpD,UACG,QAAQ,OAAO,EACf,YAAY,iCAAiC,EAC7C,SAAS,cAAc,gDAAgD,EACvE,OAAO,kBAAkB,4CAA4C,EACrE,OAAO,wBAAwB,yCAAyC,EACxE,OAAO,gBAAgB,qCAAqC,EAC5D,OAAO,kBAAkB,uCAAuC,EAChE,OAAO,gBAAgB,aAAa,EACpC,OAAO,oBAAoB,mBAAmB,KAAK,EACnD,OAAO,0BAA0B,uBAAuB,GAAG,EAC3D,OAAO,oBAAoB,6BAA6B,EACxD,OAAO,mBAAmB,sBAAsB,EAChD;AAAA,IACC;AAAA,IACA;AAAA,IACA,4BAA4B,SAAS;AAAA,EACvC,EACC,OAAO,uBAAuB,sCAAsC,KAAK,EACzE,OAAO,+BAA+B,4BAA4B,KAAK,EACvE;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,aAAa,mDAAmD,KAAK,EAC5E,OAAO,OAAO,UAA8B,YAAgD;AAC3F,UAAM,YAAY,UAAU,OAAO;AAAA,EACrC,CAAC;AACL;AAEA,SAAS,cAAc,SAA2B;AAChD,SAAO,QACJ,OAAO,gBAAgB,EACvB,OAAO,wBAAwB,6BAA6B,EAC5D,OAAO,cAAc,EACrB,OAAO,gBAAgB,EACvB,OAAO,cAAc,EACrB,OAAO,oBAAoB,mBAAmB,KAAK,EACnD,OAAO,0BAA0B,uBAAuB,GAAG,EAC3D,OAAO,oBAAoB,gCAAgC;AAChE;AAEA,SAAS,oBAAoB,SAAwB;AACnD;AAAA,IACE,QACG,QAAQ,MAAM,EACd,YAAY,+DAA+D,EAC3E,SAAS,cAAc,gDAAgD;AAAA,EAC5E,EACG,OAAO,mBAAmB,EAC1B;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,IAEA;AAAA,EACF,EACC;AAAA,IACC,OACE,UACA,SACA,YACkB;AAClB,YAAM,WAAW,UAAU,SAAS,OAAO;AAAA,IAC7C;AAAA,EACF;AACJ;AAEA,SAAS,qBAAqB,SAAwB;AACpD,UACG,QAAQ,MAAM,EACd,YAAY,6CAA6C,EACzD,OAAO,YAA2B;AACjC,UAAM,WAAW;AAAA,EACnB,CAAC;AACH;AAAA,IACE,QACG,QAAQ,QAAQ,EAChB,YAAY,oEAAoE,EAChF,SAAS,cAAc,gDAAgD;AAAA,EAC5E,EACG,OAAO,qBAAqB,2BAA2B,EACvD,OAAO,OAAO,UAA8B,YAAiD;AAC9F,UAAM,aAAa,UAAU,OAAO;AAAA,EACtC,CAAC;AACD,UACG,QAAQ,QAAQ,EAChB,YAAY,+EAA+E,EAC3F,OAAO,aAAa,iEAAiE,KAAK,EAC1F,OAAO,OAAO,YAA2D;AACxE,UAAM,aAAa,QAAQ,YAAY,IAAI;AAAA,EAC7C,CAAC;AACL;AAEA,eAAsB,KAAK,MAAwC;AACjE,QAAM,UAAU,IAAI,QAAQ,EACzB,KAAK,aAAa,EAClB,YAAY,uEAAuE,EACnF,QAAQ,mBAAmB,CAAC;AAC/B,uBAAqB,OAAO;AAC5B,sBAAoB,OAAO;AAC3B,uBAAqB,OAAO;AAC5B,QAAM,QAAQ,WAAW,CAAC,GAAG,IAAI,CAAC;AACpC;AAEA,SAAS,mBAAmB,OAAsB;AAChD,MAAI,iBAAiB,iBAAiB;AACpC,QAAI,MAAM,SAAS,WAAW;AAC5B,kBAAY,OAAO,MAAM,YAAY,MAAM,OAAO;AAAA,CAAI;AACtD,kBAAY,KAAK,iBAAiB,KAAK,CAAC;AAAA,IAC1C;AACA,gBAAY,OAAO,MAAM,UAAU,MAAM,IAAI,MAAM,MAAM,OAAO;AAAA,CAAI;AACpE,QAAI,MAAM,WAAW,UAAa,MAAM,OAAO,KAAK,EAAE,SAAS,GAAG;AAChE,kBAAY,OAAO,MAAM;AAAA,EAA4B,MAAM,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,IAC9E;AACA,gBAAY,KAAK,iBAAiB,KAAK,CAAC;AAAA,EAC1C;AACA,MAAI,4BAA4B,KAAK,GAAG;AACtC,UAAMA,WAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,gBAAY,OAAO,MAAM,yBAAyBA,QAAO;AAAA,CAAI;AAC7D,gBAAY,KAAK,yBAAyB;AAAA,EAC5C;AACA,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAY,OAAO,MAAM,UAAU,OAAO;AAAA,CAAI;AAC9C,cAAY,KAAK,iBAAiB,KAAK,CAAC;AAC1C;AAEA,IAAI;AACF,QAAM,KAAK,YAAY,IAAI;AAC7B,SAAS,OAAgB;AACvB,qBAAmB,KAAK;AAC1B;","names":["message"]}
package/dist/index.d.ts CHANGED
@@ -71,6 +71,28 @@ interface SessionHealthVerdict {
71
71
 
72
72
  declare function sessionKeyString(key: SessionKey): string;
73
73
 
74
+ type DoctorLegacyLiveness = "alive" | "not-running" | "unverified";
75
+ interface DoctorLegacySessionFinding {
76
+ readonly index: number;
77
+ readonly sessionId?: string;
78
+ readonly pid?: number;
79
+ readonly localPort?: number;
80
+ readonly hostname?: string;
81
+ readonly liveness: DoctorLegacyLiveness;
82
+ readonly reason?: string;
83
+ }
84
+ interface DoctorLegacyFinding {
85
+ readonly statePath: string;
86
+ readonly statePresent: boolean;
87
+ readonly homesPath: string;
88
+ readonly homesPresent: boolean;
89
+ readonly homeCount?: number;
90
+ readonly sessions?: readonly DoctorLegacySessionFinding[];
91
+ readonly inspectionWarnings?: readonly string[];
92
+ readonly warning?: string;
93
+ readonly manualRemovalCommand?: string;
94
+ }
95
+
74
96
  type DoctorCleanupStatus = "not-requested" | "not-eligible" | "removed" | "skipped" | "failed";
75
97
  interface DoctorSessionFinding {
76
98
  readonly session: ActiveSession;
@@ -81,6 +103,7 @@ interface DoctorHomeFinding {
81
103
  readonly path: string;
82
104
  readonly cleanupEligible: boolean;
83
105
  readonly cleanupStatus: DoctorCleanupStatus;
106
+ readonly reason?: string;
84
107
  }
85
108
  interface DoctorPortFinding {
86
109
  readonly port: number;
@@ -96,13 +119,7 @@ interface DoctorArtifactFinding {
96
119
  readonly cleanupEligible: boolean;
97
120
  readonly cleanupStatus: DoctorCleanupStatus;
98
121
  readonly cleanupError?: string;
99
- }
100
- interface DoctorLegacyFinding {
101
- readonly statePath: string;
102
- readonly statePresent: boolean;
103
- readonly homesPath: string;
104
- readonly homesPresent: boolean;
105
- readonly warning?: string;
122
+ readonly note?: string;
106
123
  readonly manualRemovalCommand?: string;
107
124
  }
108
125
  interface DoctorReport {
@@ -133,13 +150,14 @@ interface StopDebuggerResult extends ActiveSession {
133
150
  interface StopAllOutcome {
134
151
  readonly sessionId: string;
135
152
  readonly app: string;
136
- readonly status: "failed" | "pending" | "stale" | "stopped";
153
+ readonly status: "failed" | "forced" | "pending" | "stale" | "stopped";
137
154
  readonly result?: StopDebuggerResult;
138
155
  readonly error?: CfDebuggerError;
139
156
  }
140
157
  interface StopAllResult {
141
158
  readonly outcomes: readonly StopAllOutcome[];
142
159
  readonly failed: number;
160
+ readonly forced: number;
143
161
  readonly pending: number;
144
162
  readonly stale: number;
145
163
  readonly stopped: number;
@@ -188,4 +206,4 @@ declare function resolveNodeTarget(input: NodeTargetSelectors): ResolvedNodeTarg
188
206
  declare function buildNodeInspectorCommand(nodePid?: number, remotePort?: number): string;
189
207
  declare function parseNodeInspectorMarkers(stdout: string, remotePort?: number): NodeProcessSelection;
190
208
 
191
- export { type ActiveSession, CfDebuggerError, type CurrentCfTarget, type CurrentCfTargetReadOptions, DEFAULT_NODE_INSPECTOR_PORT, type DebuggerHandle, type DoctorArtifactFinding, type DoctorArtifactKind, type DoctorCleanupStatus, type DoctorHomeFinding, type DoctorLegacyFinding, type DoctorOptions, type DoctorPortFinding, type DoctorReport, type DoctorSessionFinding, type NodeProcessSelection, type NodeTargetSelectors, type ResolvedNodeTarget, type ResolvedSessionKey, type SessionKey, type SessionStatus, type StartDebuggerOptions, type StopAllOutcome, type StopAllResult, type StopDebuggerResult, type StopOptions, buildNodeInspectorCommand, getSession, listKnownRegionKeys, listSessions, parseCurrentCfTarget, parseNodeInspectorMarkers, readCurrentCfTarget, regionKeyForApiEndpoint, regionKeyFromSapApiEndpoint, requireCurrentCfRegion, resolveApiEndpoint, resolveNodeTarget, runDoctor, sessionKeyString, startDebugger, stopAllDebuggers, stopDebugger };
209
+ export { type ActiveSession, CfDebuggerError, type CurrentCfTarget, type CurrentCfTargetReadOptions, DEFAULT_NODE_INSPECTOR_PORT, type DebuggerHandle, type DoctorArtifactFinding, type DoctorArtifactKind, type DoctorCleanupStatus, type DoctorHomeFinding, type DoctorLegacyFinding, type DoctorLegacyLiveness, type DoctorLegacySessionFinding, type DoctorOptions, type DoctorPortFinding, type DoctorReport, type DoctorSessionFinding, type NodeProcessSelection, type NodeTargetSelectors, type ResolvedNodeTarget, type ResolvedSessionKey, type SessionKey, type SessionStatus, type StartDebuggerOptions, type StopAllOutcome, type StopAllResult, type StopDebuggerResult, type StopOptions, buildNodeInspectorCommand, getSession, listKnownRegionKeys, listSessions, parseCurrentCfTarget, parseNodeInspectorMarkers, readCurrentCfTarget, regionKeyForApiEndpoint, regionKeyFromSapApiEndpoint, requireCurrentCfRegion, resolveApiEndpoint, resolveNodeTarget, runDoctor, sessionKeyString, startDebugger, stopAllDebuggers, stopDebugger };
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  startDebugger,
19
19
  stopAllDebuggers,
20
20
  stopDebugger
21
- } from "./chunk-ZWAQD7KL.js";
21
+ } from "./chunk-QBB4N2WN.js";
22
22
  export {
23
23
  CfDebuggerError,
24
24
  DEFAULT_NODE_INSPECTOR_PORT,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saptools/cf-debugger",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Open an SSH debug tunnel to a SAP BTP Cloud Foundry app's Node.js inspector — from any terminal, no IDE required.",
5
5
  "type": "module",
6
6
  "publishConfig": {