@saptools/cf-live-trace 0.1.5 → 0.1.6

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
@@ -112,6 +112,8 @@ function spawnPortForward(params) {
112
112
  env: buildCfEnv(params.cfHomeDir),
113
113
  stdio: ["ignore", "pipe", "pipe"]
114
114
  });
115
+ child.stdout.resume();
116
+ child.stderr.resume();
115
117
  return {
116
118
  process: child,
117
119
  localPort: params.localPort,
@@ -265,7 +267,11 @@ function extractErrorDetail(error) {
265
267
  if (stderr.length > 0) {
266
268
  return stderr;
267
269
  }
268
- return error["message"] instanceof Error ? error["message"].message : "";
270
+ const message = error["message"];
271
+ if (typeof message === "string") {
272
+ return message.trim();
273
+ }
274
+ return message instanceof Error ? message.message.trim() : "";
269
275
  }
270
276
  function formatErrorMessage(error) {
271
277
  const message = error instanceof Error ? error.message : String(error);
@@ -629,7 +635,7 @@ function isRecord2(value) {
629
635
 
630
636
  // src/runtime-source.ts
631
637
  var CF_LIVE_TRACE_GLOBAL_NAME = "__SAPTOOLS_CF_LIVE_TRACE__";
632
- var CF_LIVE_TRACE_RUNTIME_VERSION = 1;
638
+ var CF_LIVE_TRACE_RUNTIME_VERSION = 2;
633
639
  var CF_LIVE_TRACE_RUNTIME_SOURCE = `
634
640
  (() => {
635
641
  const name = '${CF_LIVE_TRACE_GLOBAL_NAME}';
@@ -826,15 +832,12 @@ var CF_LIVE_TRACE_RUNTIME_SOURCE = `
826
832
  status() {
827
833
  return { installed: state.installed, enabled: state.enabled, queueSize: state.queue.length, droppedCount: state.droppedCount, maxEvents: state.options.maxEvents };
828
834
  },
829
- uninstall() {
835
+ async uninstall() {
830
836
  state.enabled = false;
831
- const requireFn = loadRequire();
832
- if (requireFn) {
833
- const http = requireFn('http');
834
- const https = requireFn('https');
835
- if (state.originals.httpServerEmit && http && http.Server) http.Server.prototype.emit = state.originals.httpServerEmit;
836
- if (state.originals.httpsServerEmit && https && https.Server) https.Server.prototype.emit = state.originals.httpsServerEmit;
837
- }
837
+ const http = await loadModule('http');
838
+ const https = await loadModule('https');
839
+ if (state.originals.httpServerEmit && http && http.Server) http.Server.prototype.emit = state.originals.httpServerEmit;
840
+ if (state.originals.httpsServerEmit && https && https.Server) https.Server.prototype.emit = state.originals.httpsServerEmit;
838
841
  state.installed = false;
839
842
  return api.status();
840
843
  }
@@ -974,6 +977,9 @@ var LiveTraceSession = class {
974
977
  async stop(options) {
975
978
  this.stopRequested = true;
976
979
  if (!this.isRunning()) {
980
+ if (this.state === "error" && options.reason === "error") {
981
+ return;
982
+ }
977
983
  this.postState("stopped", `Trace stopped (${options.reason}).`, false, false);
978
984
  return;
979
985
  }
@@ -1406,12 +1412,14 @@ async function runTraceCommand(options) {
1406
1412
  try {
1407
1413
  const events = [];
1408
1414
  const eventLimit = createEventLimit(options);
1415
+ const runtimeError = createRuntimeErrorStopWaiter();
1409
1416
  const session = new LiveTraceSession({
1410
1417
  target: { ...options.target, cfHomeDir: cfHome.path },
1411
1418
  onState: (event) => {
1412
1419
  if (!options.quiet) {
1413
1420
  writeProgress(event);
1414
1421
  }
1422
+ runtimeError.report(event);
1415
1423
  },
1416
1424
  onLog: (message) => {
1417
1425
  if (!options.quiet) {
@@ -1423,7 +1431,7 @@ async function runTraceCommand(options) {
1423
1431
  eventLimit.check(events.length);
1424
1432
  }
1425
1433
  });
1426
- await runUntilStopped(session, options, eventLimit);
1434
+ await runUntilStopped(session, options, eventLimit, runtimeError);
1427
1435
  if (options.format === "json") {
1428
1436
  writeJson({ events });
1429
1437
  }
@@ -1442,14 +1450,14 @@ function handleEvents(batch, options, events) {
1442
1450
  }
1443
1451
  }
1444
1452
  }
1445
- async function runUntilStopped(session, options, eventLimit) {
1453
+ async function runUntilStopped(session, options, eventLimit, runtimeError) {
1446
1454
  const abort = createAbortPromise();
1447
1455
  const duration = createDurationStopWaiter(options.limits.durationMs);
1448
1456
  let stopReason = "user";
1449
1457
  let failed = false;
1450
1458
  try {
1451
1459
  await session.start(options.trace);
1452
- stopReason = await waitForStop([abort, eventLimit, duration]);
1460
+ stopReason = await waitForStop([abort, eventLimit, duration, runtimeError]);
1453
1461
  } catch (error) {
1454
1462
  failed = true;
1455
1463
  throw error;
@@ -1457,6 +1465,7 @@ async function runUntilStopped(session, options, eventLimit) {
1457
1465
  abort.cleanup();
1458
1466
  duration.cleanup();
1459
1467
  eventLimit.cleanup();
1468
+ runtimeError.cleanup();
1460
1469
  await session.stop({ uninstallRuntimeHook: options.uninstallOnExit, reason: failed ? "error" : stopReason });
1461
1470
  }
1462
1471
  }
@@ -1512,6 +1521,36 @@ function createNeverStopWaiter() {
1512
1521
  }
1513
1522
  };
1514
1523
  }
1524
+ function createRuntimeErrorStopWaiter() {
1525
+ let hasStreamed = false;
1526
+ let settled = false;
1527
+ let rejectStop = () => {
1528
+ return;
1529
+ };
1530
+ const promise = new Promise((_resolve, reject) => {
1531
+ rejectStop = reject;
1532
+ });
1533
+ promise.catch(() => {
1534
+ return;
1535
+ });
1536
+ return {
1537
+ promise,
1538
+ report: (event) => {
1539
+ if (event.state === "streaming") {
1540
+ hasStreamed = true;
1541
+ return;
1542
+ }
1543
+ if (event.state !== "error" || !hasStreamed || settled) {
1544
+ return;
1545
+ }
1546
+ settled = true;
1547
+ rejectStop(new Error(event.message));
1548
+ },
1549
+ cleanup: () => {
1550
+ settled = true;
1551
+ }
1552
+ };
1553
+ }
1515
1554
  function createEventLimit(options) {
1516
1555
  if (options.limits.maxEvents === void 0) {
1517
1556
  return {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/cli/program.ts","../src/cf.ts","../src/inspector.ts","../src/preview.ts","../src/payload.ts","../src/runtime-source.ts","../src/summary.ts","../src/session.ts","../src/cli/options.ts","../src/cli/output.ts"],"sourcesContent":["import process from \"node:process\";\n\nimport { main } from \"./cli/program.js\";\n\ntry {\n await main(process.argv);\n} catch (error) {\n process.stderr.write(`[cf-live-trace] error: ${formatCliError(error)}\\n`);\n process.exitCode = 1;\n}\n\nfunction formatCliError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n","import process from \"node:process\";\n\nimport { Command } from \"commander\";\n\nimport { createTemporaryCfHome, removeTemporaryCfHome } from \"../cf.js\";\nimport { LiveTraceSession } from \"../session.js\";\nimport type { LiveTraceEvent, LiveTraceStopReason } from \"../types.js\";\n\nimport { buildRunOptionsWithCurrentTarget, type CliFlags, type RunOptions } from \"./options.js\";\nimport { writeJson, writeJsonLine, writeLog, writeProgress, writeSummaryLine } from \"./output.js\";\n\nexport async function main(argv: readonly string[]): Promise<void> {\n const program = new Command();\n program\n .name(\"cf-live-trace\")\n .description(\"Inject a runtime HTTP trace hook into a Cloud Foundry Node.js app and stream request/response events\")\n .option(\"-r, --region <key>\", \"CF region key (default: current cf target)\")\n .option(\"--api-endpoint <url>\", \"Explicit CF API endpoint\")\n .option(\"-o, --org <name>\", \"CF org name (default: current cf target)\")\n .option(\"-s, --space <name>\", \"CF space name (default: current cf target)\")\n .requiredOption(\"-a, --app <name>\", \"CF app name\")\n .option(\"--email <value>\", \"SAP email (default: SAP_EMAIL)\")\n .option(\"--password <value>\", \"SAP password (default: SAP_PASSWORD)\")\n .option(\"-i, --instance <index>\", \"CF app instance index (default: 0)\")\n .option(\"--cf-home <dir>\", \"Use an existing CF_HOME instead of a temporary one\")\n .option(\"--cf-command <path>\", \"CF CLI executable or test shim\")\n .option(\"--duration <seconds>\", \"Stop after N seconds\")\n .option(\"--max-events <count>\", \"Stop after N trace events\")\n .option(\"--max-body-bytes <bytes>\", \"Maximum request/response preview bytes; 0 keeps unlimited previews locally\", \"4096\")\n .option(\"--no-capture-headers\", \"Do not capture request/response headers\")\n .option(\"--no-capture-request-body\", \"Do not capture request body previews\")\n .option(\"--no-capture-response-body\", \"Do not capture response body previews\")\n .option(\"--no-uninstall-on-exit\", \"Disable the runtime hook instead of uninstalling it on exit\")\n .option(\"--format <format>\", \"Output format: ndjson, summary, json\", \"ndjson\")\n .option(\"--quiet\", \"Suppress progress messages on stderr\")\n .action(async (flags: CliFlags): Promise<void> => {\n await runTraceCommand(await buildRunOptionsWithCurrentTarget(flags, process.env));\n });\n\n await program.parseAsync([...argv]);\n}\n\nexport async function runTraceCommand(options: RunOptions): Promise<void> {\n const cfHome = await resolveCfHome(options);\n try {\n const events: LiveTraceEvent[] = [];\n const eventLimit = createEventLimit(options);\n const session = new LiveTraceSession({\n target: { ...options.target, cfHomeDir: cfHome.path },\n onState: (event) => {\n if (!options.quiet) {\n writeProgress(event);\n }\n },\n onLog: (message) => {\n if (!options.quiet) {\n writeLog(message);\n }\n },\n onEvents: (batch) => {\n handleEvents(batch, options, events);\n eventLimit.check(events.length);\n },\n });\n await runUntilStopped(session, options, eventLimit);\n if (options.format === \"json\") {\n writeJson({ events });\n }\n } finally {\n await cfHome.dispose();\n }\n}\n\nfunction handleEvents(batch: readonly LiveTraceEvent[], options: RunOptions, events: LiveTraceEvent[]): void {\n for (const event of batch) {\n events.push(event);\n if (options.format === \"ndjson\") {\n writeJsonLine(event);\n }\n if (options.format === \"summary\") {\n writeSummaryLine(event);\n }\n }\n}\n\nasync function runUntilStopped(\n session: LiveTraceSession,\n options: RunOptions,\n eventLimit: StopWaiter & { readonly check: (count: number) => void },\n): Promise<void> {\n const abort = createAbortPromise();\n const duration = createDurationStopWaiter(options.limits.durationMs);\n let stopReason: LiveTraceStopReason = \"user\";\n let failed = false;\n try {\n await session.start(options.trace);\n stopReason = await waitForStop([abort, eventLimit, duration]);\n } catch (error) {\n failed = true;\n throw error;\n } finally {\n abort.cleanup();\n duration.cleanup();\n eventLimit.cleanup();\n await session.stop({ uninstallRuntimeHook: options.uninstallOnExit, reason: failed ? \"error\" : stopReason });\n }\n}\n\ninterface StopWaiter {\n readonly promise: Promise<LiveTraceStopReason>;\n cleanup(): void;\n}\n\nasync function waitForStop(waiters: readonly StopWaiter[]): Promise<LiveTraceStopReason> {\n return await Promise.race(waiters.map((waiter) => waiter.promise));\n}\n\nfunction createDurationStopWaiter(durationMs: number | undefined): StopWaiter {\n if (durationMs === undefined) {\n return createNeverStopWaiter();\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const promise = new Promise<LiveTraceStopReason>((resolve) => {\n timer = setTimeout(() => {\n resolve(\"duration\");\n }, durationMs);\n });\n return {\n promise,\n cleanup: (): void => {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n },\n };\n}\n\nfunction createAbortPromise(): { readonly promise: Promise<LiveTraceStopReason>; readonly cleanup: () => void } {\n let resolveStop: (reason: LiveTraceStopReason) => void = () => {\n return;\n };\n const promise = new Promise<LiveTraceStopReason>((resolve) => {\n resolveStop = resolve;\n });\n const onSignal = (): void => {\n resolveStop(\"user\");\n };\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n return {\n promise,\n cleanup: (): void => {\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n },\n };\n}\n\nfunction createNeverStopWaiter(): StopWaiter {\n return {\n promise: new Promise<LiveTraceStopReason>(() => {\n return;\n }),\n cleanup: (): void => {\n return;\n },\n };\n}\n\nfunction createEventLimit(options: RunOptions): {\n readonly promise: Promise<LiveTraceStopReason>;\n readonly check: (count: number) => void;\n readonly cleanup: () => void;\n} {\n if (options.limits.maxEvents === undefined) {\n return {\n ...createNeverStopWaiter(),\n check: (): void => {\n return;\n },\n };\n }\n let resolveLimit: (reason: LiveTraceStopReason) => void = () => {\n return;\n };\n const promise = new Promise<LiveTraceStopReason>((resolve) => {\n resolveLimit = resolve;\n });\n return {\n promise,\n check: (count): void => {\n if (options.limits.maxEvents !== undefined && count >= options.limits.maxEvents) {\n resolveLimit(\"max-events\");\n }\n },\n cleanup: (): void => {\n return;\n },\n };\n}\n\nasync function resolveCfHome(options: RunOptions): Promise<{ readonly path: string; readonly dispose: () => Promise<void> }> {\n if (options.target.cfHomeDir !== undefined) {\n return {\n path: options.target.cfHomeDir,\n dispose: (): Promise<void> => Promise.resolve(),\n };\n }\n const path = await createTemporaryCfHome();\n return {\n path,\n dispose: async (): Promise<void> => {\n await removeTemporaryCfHome(path);\n },\n };\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { connect as netConnect, createServer } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nimport type { CfLiveTraceTarget, InspectorStartupResult, PortForwardHandle, TunnelOpenResult } from \"./types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CF_MAX_BUFFER_BYTES = 8 * 1024 * 1024;\nconst CF_COMMAND_TIMEOUT_MS = 180_000;\nconst CF_SSH_READY_TIMEOUT_MS = 60_000;\nconst INSPECTOR_SIGNAL_TIMEOUT_MS = 15_000;\nconst INSPECTOR_REMOTE_HOST = \"127.0.0.1\";\nconst INSPECTOR_REMOTE_PORT = 9229;\nconst TUNNEL_KEEPALIVE_SECONDS = 6 * 60 * 60;\nconst TUNNEL_READY_TIMEOUT_MS = 20_000;\nconst TUNNEL_READY_POLL_MS = 200;\n\nexport interface RunCfOptions {\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly envOverrides?: Record<string, string>;\n readonly timeoutMs?: number;\n readonly redactor?: (message: string) => string;\n}\n\nexport interface CfDependencies {\n runCf(args: readonly string[], options: RunCfOptions): Promise<string>;\n}\n\nexport interface TunnelDependencies {\n allocatePort(): Promise<number>;\n spawnPortForward(params: PortForwardParams): PortForwardHandle;\n waitForLocalPort(port: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean>;\n}\n\nexport interface PortForwardParams {\n readonly appName: string;\n readonly localPort: number;\n readonly remoteHost: string;\n readonly remotePort: number;\n readonly keepAliveSeconds: number;\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly instanceIndex?: number;\n}\n\nexport interface InspectorTunnelTarget {\n readonly app?: string;\n readonly appName?: string;\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly instanceIndex?: number;\n}\n\nexport async function createTemporaryCfHome(): Promise<string> {\n return await mkdtemp(join(tmpdir(), \"saptools-cf-live-trace-\"));\n}\n\nexport async function removeTemporaryCfHome(cfHomeDir: string): Promise<void> {\n await rm(cfHomeDir, { recursive: true, force: true });\n}\n\nexport async function prepareCfSession(\n target: CfLiveTraceTarget,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<void> {\n const apiEndpoint = resolveApiEndpoint(target);\n const redactor = createSecretRedactor([target.email, target.password]);\n const baseOptions = buildRunOptions(target, redactor);\n await dependencies.runCf([\"api\", apiEndpoint], baseOptions);\n await dependencies.runCf([\"auth\"], {\n ...baseOptions,\n envOverrides: { CF_USERNAME: target.email, CF_PASSWORD: target.password },\n });\n await dependencies.runCf([\"target\", \"-o\", target.org, \"-s\", target.space], baseOptions);\n}\n\nexport async function ensureSshEnabled(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<void> {\n const redactor = createSecretRedactor([target.email, target.password]);\n const options = buildRunOptions(target, redactor);\n const status = await dependencies.runCf([\"ssh-enabled\", target.app], options);\n if (parseSshStatus(status) === \"enabled\") {\n return;\n }\n await dependencies.runCf([\"enable-ssh\", target.app], options);\n await dependencies.runCf([\"restart\", target.app], options);\n await dependencies.runCf(buildCfSshArgs(target.app, target.instanceIndex, [\"-c\", \"true\"]), {\n ...options,\n timeoutMs: CF_SSH_READY_TIMEOUT_MS,\n });\n}\n\nexport async function tryStartNodeInspector(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<boolean> {\n const result = await startNodeInspector(target, dependencies);\n return result.status === \"ready\";\n}\n\nexport async function startNodeInspector(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<InspectorStartupResult> {\n const redactor = createSecretRedactor([target.email, target.password]);\n try {\n const stdout = await dependencies.runCf(\n buildCfSshArgs(target.app, target.instanceIndex, [\"-c\", buildInspectorSignalCommand()]),\n { ...buildRunOptions(target, redactor), timeoutMs: INSPECTOR_SIGNAL_TIMEOUT_MS },\n );\n return hasInspectorReadyMarker(stdout)\n ? { status: \"ready\" }\n : { status: \"not-ready\", ...optionalDetail(summarizeInspectorStartupOutput(stdout)) };\n } catch (error) {\n return { status: \"not-ready\", ...optionalDetail(redactor(formatErrorMessage(error))) };\n }\n}\n\nexport async function openInspectorTunnel(\n target: InspectorTunnelTarget,\n dependencies: TunnelDependencies = defaultTunnelDependencies,\n): Promise<TunnelOpenResult> {\n const localPort = await dependencies.allocatePort();\n const handle = dependencies.spawnPortForward(buildPortForwardParams(target, localPort));\n const ready = await raceForwardReadiness(handle, dependencies);\n if (!ready) {\n handle.stop();\n return { status: \"not-reachable\" };\n }\n return { status: \"ready\", handle };\n}\n\nexport function buildCfSshArgs(appName: string, instanceIndex: number | undefined, tail: readonly string[]): string[] {\n const args = [\"ssh\", appName];\n if (instanceIndex !== undefined) {\n args.push(\"-i\", String(instanceIndex));\n }\n return [...args, ...tail];\n}\n\nexport function buildInspectorSignalCommand(): string {\n return INSPECTOR_SIGNAL_COMMAND;\n}\n\nexport function createSecretRedactor(secrets: readonly string[]): (message: string) => string {\n const values = secrets.map((secret) => secret.trim()).filter((secret) => secret.length > 0);\n return (message: string): string => values.reduce((current, secret) => current.split(secret).join(\"<redacted>\"), message);\n}\n\nexport async function runCfCommand(args: readonly string[], options: RunCfOptions): Promise<string> {\n const command = resolveCommand(options.command);\n try {\n const { stdout } = await execFileAsync(command.bin, [...command.argsPrefix, ...args], {\n env: buildCfEnv(options.cfHomeDir, options.envOverrides),\n maxBuffer: CF_MAX_BUFFER_BYTES,\n timeout: options.timeoutMs ?? CF_COMMAND_TIMEOUT_MS,\n });\n return stdout;\n } catch (error) {\n throw new Error(formatCfError(args, error, options.redactor), { cause: error });\n }\n}\n\nexport function spawnPortForward(params: PortForwardParams): PortForwardHandle {\n const command = resolveCommand(params.command);\n const forwardSpec = `${String(params.localPort)}:${params.remoteHost}:${String(params.remotePort)}`;\n const sshArgs = buildCfSshArgs(params.appName, params.instanceIndex, [\"-L\", forwardSpec, \"-c\", `sleep ${String(params.keepAliveSeconds)}`]);\n const child = spawn(command.bin, [...command.argsPrefix, ...sshArgs], {\n env: buildCfEnv(params.cfHomeDir),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n return {\n process: child,\n localPort: params.localPort,\n stop(): void {\n if (!child.killed) {\n child.kill();\n }\n },\n };\n}\n\nexport const defaultCfDependencies: CfDependencies = {\n runCf: runCfCommand,\n};\n\nexport const defaultTunnelDependencies: TunnelDependencies = {\n allocatePort: findFreePort,\n spawnPortForward,\n waitForLocalPort,\n};\n\nfunction buildRunOptions(target: Pick<CfLiveTraceTarget, \"cfHomeDir\" | \"command\">, redactor: (message: string) => string): RunCfOptions {\n return {\n ...(target.cfHomeDir === undefined ? {} : { cfHomeDir: target.cfHomeDir }),\n ...(target.command === undefined ? {} : { command: target.command }),\n redactor,\n };\n}\n\nfunction resolveApiEndpoint(target: Pick<CfLiveTraceTarget, \"apiEndpoint\" | \"region\">): string {\n if (target.apiEndpoint !== undefined && target.apiEndpoint.trim().length > 0) {\n return target.apiEndpoint.trim();\n }\n if (target.region === undefined) {\n throw new Error(\"CF region or apiEndpoint is required.\");\n }\n const endpoint = REGION_API_ENDPOINTS[target.region];\n if (endpoint === undefined) {\n throw new Error(`Unknown CF region: ${target.region}`);\n }\n return endpoint;\n}\n\nconst REGION_API_ENDPOINTS: Readonly<Record<string, string>> = {\n ae01: \"https://api.cf.ae01.hana.ondemand.com\",\n ap01: \"https://api.cf.ap01.hana.ondemand.com\",\n ap10: \"https://api.cf.ap10.hana.ondemand.com\",\n ap11: \"https://api.cf.ap11.hana.ondemand.com\",\n ap12: \"https://api.cf.ap12.hana.ondemand.com\",\n ap20: \"https://api.cf.ap20.hana.ondemand.com\",\n ap21: \"https://api.cf.ap21.hana.ondemand.com\",\n ap30: \"https://api.cf.ap30.hana.ondemand.com\",\n br10: \"https://api.cf.br10.hana.ondemand.com\",\n br20: \"https://api.cf.br20.hana.ondemand.com\",\n br30: \"https://api.cf.br30.hana.ondemand.com\",\n ca10: \"https://api.cf.ca10.hana.ondemand.com\",\n ca20: \"https://api.cf.ca20.hana.ondemand.com\",\n ch20: \"https://api.cf.ch20.hana.ondemand.com\",\n eu10: \"https://api.cf.eu10.hana.ondemand.com\",\n eu11: \"https://api.cf.eu11.hana.ondemand.com\",\n eu12: \"https://api.cf.eu12.hana.ondemand.com\",\n eu20: \"https://api.cf.eu20.hana.ondemand.com\",\n eu21: \"https://api.cf.eu21.hana.ondemand.com\",\n eu30: \"https://api.cf.eu30.hana.ondemand.com\",\n eu31: \"https://api.cf.eu31.hana.ondemand.com\",\n in30: \"https://api.cf.in30.hana.ondemand.com\",\n jp10: \"https://api.cf.jp10.hana.ondemand.com\",\n jp20: \"https://api.cf.jp20.hana.ondemand.com\",\n jp30: \"https://api.cf.jp30.hana.ondemand.com\",\n kr30: \"https://api.cf.kr30.hana.ondemand.com\",\n us10: \"https://api.cf.us10.hana.ondemand.com\",\n us11: \"https://api.cf.us11.hana.ondemand.com\",\n us20: \"https://api.cf.us20.hana.ondemand.com\",\n us21: \"https://api.cf.us21.hana.ondemand.com\",\n us30: \"https://api.cf.us30.hana.ondemand.com\",\n us31: \"https://api.cf.us31.hana.ondemand.com\",\n};\n\nfunction regionKeyForApiEndpoint(apiEndpoint: string): string | undefined {\n const normalized = normalizeApiEndpoint(apiEndpoint);\n for (const [key, endpoint] of Object.entries(REGION_API_ENDPOINTS)) {\n if (normalizeApiEndpoint(endpoint) === normalized) {\n return key;\n }\n }\n return undefined;\n}\n\nfunction normalizeApiEndpoint(apiEndpoint: string): string {\n return apiEndpoint.trim().replace(/\\/+$/, \"\").toLowerCase();\n}\n\nfunction parseSshStatus(stdout: string): \"enabled\" | \"disabled\" {\n return stdout.toLowerCase().includes(\"enabled\") && !stdout.toLowerCase().includes(\"disabled\") ? \"enabled\" : \"disabled\";\n}\n\nfunction buildPortForwardParams(\n target: InspectorTunnelTarget,\n localPort: number,\n): PortForwardParams {\n return {\n appName: resolveTunnelAppName(target),\n localPort,\n remoteHost: INSPECTOR_REMOTE_HOST,\n remotePort: INSPECTOR_REMOTE_PORT,\n keepAliveSeconds: TUNNEL_KEEPALIVE_SECONDS,\n ...(target.cfHomeDir === undefined ? {} : { cfHomeDir: target.cfHomeDir }),\n ...(target.command === undefined ? {} : { command: target.command }),\n ...(target.instanceIndex === undefined ? {} : { instanceIndex: target.instanceIndex }),\n };\n}\n\nfunction resolveTunnelAppName(target: InspectorTunnelTarget): string {\n const appName = target.appName ?? target.app;\n if (appName === undefined || appName.trim().length === 0) {\n throw new Error(\"CF app name is required for the inspector tunnel.\");\n }\n return appName;\n}\n\nasync function raceForwardReadiness(handle: PortForwardHandle, dependencies: TunnelDependencies): Promise<boolean> {\n const controller = new AbortController();\n let markFailed: () => void = () => {\n return;\n };\n const failedEarly = new Promise<false>((resolve) => {\n markFailed = (): void => {\n resolve(false);\n };\n handle.process.once(\"exit\", markFailed);\n handle.process.once(\"error\", markFailed);\n });\n const ready = dependencies.waitForLocalPort(handle.localPort, TUNNEL_READY_TIMEOUT_MS, controller.signal);\n try {\n return await Promise.race([ready, failedEarly]);\n } finally {\n controller.abort();\n handle.process.removeListener(\"exit\", markFailed);\n handle.process.removeListener(\"error\", markFailed);\n }\n}\n\nfunction resolveCommand(command?: string): { readonly bin: string; readonly argsPrefix: readonly string[] } {\n const resolvedBin = command ?? process.env[\"CF_LIVE_TRACE_CF_BIN\"] ?? \"cf\";\n return /\\.(?:c|m)?js$/i.test(resolvedBin)\n ? { bin: process.execPath, argsPrefix: [resolvedBin] }\n : { bin: resolvedBin, argsPrefix: [] };\n}\n\nfunction buildCfEnv(cfHomeDir?: string, envOverrides?: Record<string, string>): NodeJS.ProcessEnv {\n const env = { ...process.env };\n delete env[\"SAP_EMAIL\"];\n delete env[\"SAP_PASSWORD\"];\n if (cfHomeDir !== undefined && cfHomeDir.length > 0) {\n env[\"CF_HOME\"] = cfHomeDir;\n }\n return envOverrides === undefined ? env : { ...env, ...envOverrides };\n}\n\nfunction formatCfError(args: readonly string[], error: unknown, redactor?: (message: string) => string): string {\n const detail = extractErrorDetail(error);\n const message = `cf ${formatArgs(args)} failed${detail.length > 0 ? `: ${detail}` : \".\"}`;\n return redactor?.(message) ?? message;\n}\n\nfunction extractErrorDetail(error: unknown): string {\n if (!isRecord(error)) {\n return \"\";\n }\n const stderr = typeof error[\"stderr\"] === \"string\" ? error[\"stderr\"].trim() : \"\";\n if (stderr.length > 0) {\n return stderr;\n }\n return error[\"message\"] instanceof Error ? error[\"message\"].message : \"\";\n}\n\nfunction formatErrorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n\nfunction formatArgs(args: readonly string[]): string {\n return args.join(\" \");\n}\n\nfunction hasInspectorReadyMarker(stdout: string): boolean {\n return stdout.split(/\\r?\\n/).map((line) => line.trim()).includes(\"saptools-inspector-ready\");\n}\n\nfunction summarizeInspectorStartupOutput(stdout: string): string | undefined {\n const markers = stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"saptools-inspector-\"));\n return markers.length === 0 ? undefined : markers.join(\"; \");\n}\n\nfunction optionalDetail(detail: string | undefined): { readonly detail?: string } {\n return detail === undefined || detail.length === 0 ? {} : { detail };\n}\n\nfunction findFreePort(): Promise<number> {\n return new Promise<number>((resolve, reject) => {\n const server = createServer();\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n const port = typeof address === \"object\" && address !== null ? address.port : 0;\n server.close(() => {\n if (port === 0) {\n reject(new Error(\"Failed to allocate a local port.\"));\n return;\n }\n resolve(port);\n });\n });\n });\n}\n\nfunction waitForLocalPort(port: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n return new Promise<boolean>((resolve) => {\n let activeSocket: ReturnType<typeof netConnect> | undefined;\n let settled = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n const finish = (ready: boolean): void => {\n if (settled) {\n return;\n }\n settled = true;\n if (retryTimer !== undefined) {\n clearTimeout(retryTimer);\n }\n activeSocket?.destroy();\n activeSocket = undefined;\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(ready);\n };\n const onAbort = (): void => {\n finish(false);\n };\n const attempt = (): void => {\n if (settled) {\n return;\n }\n const socket = netConnect({ host: \"127.0.0.1\", port });\n activeSocket = socket;\n socket.once(\"connect\", () => {\n socket.destroy();\n activeSocket = undefined;\n finish(true);\n });\n socket.once(\"error\", () => {\n activeSocket = undefined;\n retryPortProbe(socket, deadline, attempt, finish, (timer) => {\n retryTimer = timer;\n });\n });\n };\n if (signal?.aborted === true) {\n finish(false);\n return;\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n attempt();\n });\n}\n\nfunction retryPortProbe(\n socket: ReturnType<typeof netConnect>,\n deadline: number,\n attempt: () => void,\n finish: (ready: boolean) => void,\n setRetryTimer: (timer: ReturnType<typeof setTimeout>) => void,\n): void {\n socket.destroy();\n if (Date.now() >= deadline) {\n finish(false);\n return;\n }\n setRetryTimer(setTimeout(attempt, TUNNEL_READY_POLL_MS));\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport interface CurrentCfTarget {\n readonly apiEndpoint: string;\n readonly regionKey?: string;\n readonly orgName: string;\n readonly spaceName: string;\n}\n\nexport interface CurrentCfTargetReadOptions {\n readonly command?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly timeoutMs?: number;\n}\n\nconst CURRENT_TARGET_TIMEOUT_MS = 30_000;\n\nexport async function readCurrentCfTarget(\n options?: CurrentCfTargetReadOptions,\n): Promise<CurrentCfTarget | undefined> {\n const opts = options ?? {};\n const command = resolveCommand(opts.command);\n const env = buildCfEnvForTarget(opts.env);\n try {\n const { stdout } = await execFileAsync(command.bin, [...command.argsPrefix, \"target\"], {\n env,\n maxBuffer: CF_MAX_BUFFER_BYTES,\n timeout: opts.timeoutMs ?? CURRENT_TARGET_TIMEOUT_MS,\n });\n return parseCurrentCfTarget(stdout);\n } catch {\n return undefined;\n }\n}\n\nexport function parseCurrentCfTarget(stdout: string): CurrentCfTarget | undefined {\n const fields = parseTargetFields(stdout);\n const apiEndpoint = fields.get(\"api endpoint\");\n const org = fields.get(\"org\");\n const space = fields.get(\"space\");\n if (!apiEndpoint || !org || !space) {\n return undefined;\n }\n const regionKey = regionKeyForApiEndpoint(apiEndpoint);\n return {\n apiEndpoint,\n ...(regionKey === undefined ? {} : { regionKey }),\n orgName: org,\n spaceName: space,\n };\n}\n\nfunction parseTargetFields(stdout: string): Map<string, string> {\n const map = new Map<string, string>();\n for (const line of stdout.split(/\\r?\\n/)) {\n const idx = line.indexOf(\":\");\n if (idx < 0) {\n continue;\n }\n const key = line.slice(0, idx).trim().toLowerCase();\n const val = line.slice(idx + 1).trim();\n if (key.length > 0 && val.length > 0) {\n map.set(key, val);\n }\n }\n return map;\n}\n\nfunction buildCfEnvForTarget(overrides?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const env = { ...process.env, ...overrides };\n delete env[\"SAP_EMAIL\"];\n delete env[\"SAP_PASSWORD\"];\n return env;\n}\n\nconst INSPECTOR_SIGNAL_COMMAND = [\n 'inspector_url=\"http://127.0.0.1:9229/json/list\"',\n 'inspector_ready() { ((command -v curl >/dev/null 2>&1 && curl -fsS --max-time 1 \"$inspector_url\" >/dev/null 2>&1) || (command -v wget >/dev/null 2>&1 && wget -qO- -T 1 \"$inspector_url\" >/dev/null 2>&1)); }',\n \"if inspector_ready; then\",\n \"echo saptools-inspector-ready\",\n \"exit 0\",\n \"fi\",\n 'node_pid=\"\"',\n \"best_score=-1\",\n \"for pid_dir in /proc/[0-9]*; do\",\n '[ -d \"$pid_dir\" ] || continue',\n 'node_exe=\"$(readlink \"$pid_dir/exe\" 2>/dev/null || true)\"',\n '[ \"${node_exe##*/}\" = \"node\" ] || continue',\n 'node_cmdline=\"$(tr \"\\\\000\" \" \" < \"$pid_dir/cmdline\" 2>/dev/null || true)\"',\n '[ -n \"$node_cmdline\" ] || continue',\n \"score=10\",\n 'if printf \"%s\\\\n\" \"$node_cmdline\" | grep -Eq \"@sap/cds|cds/bin/serve|serve\\\\.js|server\\\\.js|app\\\\.js|dist|build|index\\\\.js\"; then',\n \"score=20\",\n \"fi\",\n 'if [ \"$score\" -gt \"$best_score\" ]; then',\n 'best_score=\"$score\"',\n 'node_pid=\"${pid_dir##*/}\"',\n \"fi\",\n \"done\",\n 'if [ -z \"$node_pid\" ]; then',\n \"echo saptools-inspector-node-not-found\",\n \"exit 0\",\n \"fi\",\n 'echo \"saptools-inspector-node-pid=$node_pid\"',\n 'if kill -USR1 \"$node_pid\" 2>/dev/null; then',\n \"echo saptools-inspector-signaled\",\n \"else\",\n \"echo saptools-inspector-signal-failed\",\n \"exit 0\",\n \"fi\",\n \"attempt=0\",\n 'while [ \"$attempt\" -lt 20 ]; do',\n \"if inspector_ready; then\",\n \"echo saptools-inspector-ready\",\n \"exit 0\",\n \"fi\",\n \"attempt=$((attempt + 1))\",\n \"sleep 0.25\",\n \"done\",\n \"echo saptools-inspector-not-ready\",\n].join(\"\\\\n\");\n","import { connectInspector } from \"@saptools/cf-inspector\";\nimport type { InspectorSession } from \"@saptools/cf-inspector\";\n\nimport type { InspectorRuntimeClient } from \"./types.js\";\n\ninterface RuntimeEvaluateResult {\n readonly result?: { readonly value?: unknown };\n readonly exceptionDetails?: unknown;\n}\n\nexport async function connectRuntimeInspector(localPort: number): Promise<InspectorRuntimeClient> {\n const session = await connectInspector({ port: localPort, host: \"127.0.0.1\" });\n return new CdpRuntimeClient(session);\n}\n\nclass CdpRuntimeClient implements InspectorRuntimeClient {\n public constructor(private readonly session: InspectorSession) {}\n\n public async evaluate(expression: string, timeoutMs: number): Promise<unknown> {\n const result = await raceEvaluate(\n this.session.client.send<RuntimeEvaluateResult>(\"Runtime.evaluate\", {\n expression,\n awaitPromise: true,\n returnByValue: true,\n silent: true,\n }),\n timeoutMs,\n );\n return extractEvaluateValue(result);\n }\n\n public async close(): Promise<void> {\n await this.session.dispose();\n }\n}\n\nasync function raceEvaluate(promise: Promise<RuntimeEvaluateResult>, timeoutMs: number): Promise<RuntimeEvaluateResult> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(\"Runtime.evaluate timed out.\"));\n }, timeoutMs);\n });\n try {\n return await Promise.race([promise, timeout]);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n promise.catch(() => {\n return;\n });\n }\n}\n\nfunction extractEvaluateValue(result: RuntimeEvaluateResult): unknown {\n if (result.exceptionDetails !== undefined) {\n throw new Error(\"Runtime.evaluate failed.\");\n }\n return result.result?.value;\n}\n","export interface PreviewTruncationResult {\n readonly preview: string;\n readonly truncated: boolean;\n}\n\nexport function truncatePreview(preview: string, maxChars: number): PreviewTruncationResult {\n if (maxChars <= 0) {\n return { preview, truncated: false };\n }\n if (preview.length <= maxChars) {\n return { preview, truncated: false };\n }\n return { preview: preview.slice(0, maxChars), truncated: true };\n}\n","import { truncatePreview } from \"./preview.js\";\nimport type { DrainParseResult, LiveTraceEvent } from \"./types.js\";\n\nexport interface DrainParseOptions {\n readonly appId: string;\n readonly maxBodyBytes: number;\n}\n\nlet fallbackEventId = 0;\n\nexport function parseDrainResult(payload: unknown, options: DrainParseOptions): DrainParseResult {\n if (!isRecord(payload)) {\n return { events: [], droppedCount: 0, queueSize: 0 };\n }\n const rawEvents = Array.isArray(payload[\"events\"]) ? payload[\"events\"] : [];\n return {\n events: rawEvents\n .map((event) => parseRuntimeEvent(event, options))\n .filter((event): event is LiveTraceEvent => event !== null),\n droppedCount: readNonNegativeNumber(payload[\"droppedCount\"]),\n queueSize: readNonNegativeNumber(payload[\"queueSize\"]),\n };\n}\n\nfunction parseRuntimeEvent(payload: unknown, options: DrainParseOptions): LiveTraceEvent | null {\n if (!isRecord(payload)) {\n return null;\n }\n const rawUrl = readString(payload[\"url\"]) ?? readString(payload[\"normalizedUrl\"]) ?? readString(payload[\"path\"]);\n if (rawUrl === null) {\n return null;\n }\n const requestBody = limitBodyPreview(readString(payload[\"requestBodyPreview\"]) ?? \"\", options.maxBodyBytes);\n const responseBody = limitBodyPreview(readString(payload[\"responseBodyPreview\"]) ?? \"\", options.maxBodyBytes);\n return buildEvent(payload, rawUrl, requestBody, responseBody, options);\n}\n\nfunction buildEvent(\n payload: Record<string, unknown>,\n rawUrl: string,\n requestBody: { readonly preview: string; readonly truncated: boolean },\n responseBody: { readonly preview: string; readonly truncated: boolean },\n options: DrainParseOptions,\n): LiveTraceEvent {\n return {\n id: readString(payload[\"id\"]) ?? nextFallbackEventId(),\n timestamp: readString(payload[\"timestamp\"]) ?? new Date().toISOString(),\n appId: options.appId,\n instance: readString(payload[\"instance\"]) ?? \"0\",\n method: (readString(payload[\"method\"]) ?? \"GET\").toUpperCase(),\n path: readString(payload[\"path\"]) ?? normalizePath(rawUrl),\n url: rawUrl,\n normalizedUrl: readString(payload[\"normalizedUrl\"]) ?? normalizePath(rawUrl),\n status: readNullableNumber(payload[\"status\"]),\n durationMs: readNullableNumber(payload[\"durationMs\"]),\n requestBytes: readNonNegativeNumber(payload[\"requestBytes\"]),\n responseBytes: readNonNegativeNumber(payload[\"responseBytes\"]),\n requestHeaders: readHeaders(payload[\"requestHeaders\"]),\n responseHeaders: readHeaders(payload[\"responseHeaders\"]),\n requestBodyPreview: requestBody.preview,\n responseBodyPreview: responseBody.preview,\n requestBodyTruncated: payload[\"requestBodyTruncated\"] === true || requestBody.truncated,\n responseBodyTruncated: payload[\"responseBodyTruncated\"] === true || responseBody.truncated,\n droppedBeforeEvent: readNonNegativeNumber(payload[\"droppedBeforeEvent\"]),\n source: \"runtime-http\",\n traceId: readString(payload[\"traceId\"]) ?? readString(payload[\"id\"]) ?? \"\",\n correlationId: readString(payload[\"correlationId\"]),\n };\n}\n\nfunction readHeaders(value: unknown): Record<string, string> {\n if (!isRecord(value)) {\n return {};\n }\n const headers: Record<string, string> = {};\n for (const [key, rawValue] of Object.entries(value)) {\n const header = readHeaderValue(rawValue);\n if (header !== null) {\n headers[key] = header;\n }\n }\n return headers;\n}\n\nfunction readHeaderValue(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item)).join(\", \");\n }\n return null;\n}\n\nfunction limitBodyPreview(preview: string, maxChars: number): { readonly preview: string; readonly truncated: boolean } {\n return truncatePreview(preview, maxChars);\n}\n\nfunction normalizePath(rawUrl: string): string {\n try {\n const parsed = new URL(rawUrl, \"https://saptools.local\");\n return `${parsed.pathname}${parsed.search}`;\n } catch {\n return rawUrl;\n }\n}\n\nfunction readString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction readNullableNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction readNonNegativeNumber(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? value : 0;\n}\n\nfunction nextFallbackEventId(): string {\n fallbackEventId += 1;\n return `runtime-${String(fallbackEventId)}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","export const CF_LIVE_TRACE_GLOBAL_NAME = \"__SAPTOOLS_CF_LIVE_TRACE__\";\nexport const CF_LIVE_TRACE_RUNTIME_VERSION = 1;\n\nexport interface RuntimeInstallOptions {\n readonly appId: string;\n readonly instance: string;\n readonly captureHeaders: boolean;\n readonly captureRequestBody: boolean;\n readonly captureResponseBody: boolean;\n readonly maxBodyBytes: number;\n readonly maxEvents: number;\n}\n\nexport interface StopExpressionOptions {\n readonly uninstallRuntimeHook: boolean;\n}\n\nexport const CF_LIVE_TRACE_RUNTIME_SOURCE = `\n(() => {\n const name = '${CF_LIVE_TRACE_GLOBAL_NAME}';\n const runtimeVersion = ${String(CF_LIVE_TRACE_RUNTIME_VERSION)};\n const existing = globalThis[name];\n if (existing && typeof existing.version === 'number' && existing.version >= runtimeVersion) return existing;\n if (existing && typeof existing.uninstall === 'function') {\n try {\n existing.uninstall();\n } catch {}\n }\n let BufferCtor = globalThis.Buffer;\n const state = {\n version: runtimeVersion,\n installed: false,\n enabled: false,\n options: { appId: '', instance: '0', captureHeaders: true, captureRequestBody: true, captureResponseBody: true, maxBodyBytes: 4096, maxEvents: 1000 },\n queue: [],\n droppedCount: 0,\n originals: {},\n seen: new WeakSet(),\n nextId: 1\n };\n const loadRequire = () => {\n if (typeof require === 'function') return require;\n if (globalThis.process && globalThis.process.mainModule && typeof globalThis.process.mainModule.require === 'function') {\n return globalThis.process.mainModule.require.bind(globalThis.process.mainModule);\n }\n return null;\n };\n const loadModule = async (moduleName) => {\n const requireFn = loadRequire();\n if (requireFn) return requireFn(moduleName);\n if (globalThis.process && typeof globalThis.process.getBuiltinModule === 'function') {\n return globalThis.process.getBuiltinModule(moduleName);\n }\n return await import('node:' + moduleName);\n };\n const toHeaderRecord = (headers) => {\n const output = {};\n if (!headers || !state.options.captureHeaders) return output;\n for (const key of Object.keys(headers)) {\n const value = headers[key];\n output[key] = Array.isArray(value) ? value.join(', ') : String(value);\n }\n return output;\n };\n const chunkText = (chunk) => {\n if (chunk === undefined || chunk === null) return '';\n if (BufferCtor && BufferCtor.isBuffer(chunk)) return chunk.toString('utf8');\n if (typeof chunk === 'string') return chunk;\n if (chunk instanceof Uint8Array && BufferCtor) return BufferCtor.from(chunk).toString('utf8');\n return '';\n };\n const byteLength = (text) => BufferCtor ? BufferCtor.byteLength(text) : text.length;\n const appendPreview = (current, chunk, enabled) => {\n if (!enabled) return current;\n const text = chunkText(chunk);\n if (state.options.maxBodyBytes <= 0) return current + text;\n if (current.length >= state.options.maxBodyBytes) return current;\n return (current + text).slice(0, state.options.maxBodyBytes);\n };\n const enqueue = (event) => {\n if (state.queue.length >= state.options.maxEvents) {\n state.queue.shift();\n state.droppedCount += 1;\n }\n state.queue.push(event);\n };\n const observe = (req, res) => {\n if (!state.enabled || !req || !res || state.seen.has(req)) return;\n state.seen.add(req);\n const started = Date.now();\n const initialUrl = String(req.url || '');\n const traceId = String(state.nextId++);\n let requestBytes = 0;\n let responseBytes = 0;\n let requestPreview = '';\n let responsePreview = '';\n let finished = false;\n const originalReqEmit = req.emit;\n const originalWrite = res.write;\n const originalEnd = res.end;\n req.emit = function patchedReqEmit(eventName, ...args) {\n if (eventName === 'data' && args[0] !== undefined) {\n const text = chunkText(args[0]);\n requestBytes += byteLength(text);\n requestPreview = appendPreview(requestPreview, args[0], state.options.captureRequestBody);\n }\n return originalReqEmit.apply(this, [eventName, ...args]);\n };\n res.write = function patchedWrite(chunk, ...args) {\n const text = chunkText(chunk);\n responseBytes += byteLength(text);\n responsePreview = appendPreview(responsePreview, chunk, state.options.captureResponseBody);\n return originalWrite.apply(this, [chunk, ...args]);\n };\n res.end = function patchedEnd(chunk, ...args) {\n if (chunk !== undefined) {\n const text = chunkText(chunk);\n responseBytes += byteLength(text);\n responsePreview = appendPreview(responsePreview, chunk, state.options.captureResponseBody);\n }\n return originalEnd.apply(this, [chunk, ...args]);\n };\n const finish = () => {\n if (finished) return;\n finished = true;\n req.emit = originalReqEmit;\n res.write = originalWrite;\n res.end = originalEnd;\n const rawUrl = initialUrl || String(req.url || '');\n enqueue({\n id: traceId,\n timestamp: new Date().toISOString(),\n instance: state.options.instance,\n method: String(req.method || 'GET').toUpperCase(),\n path: rawUrl.split('?')[0] || rawUrl,\n url: rawUrl,\n normalizedUrl: rawUrl,\n status: typeof res.statusCode === 'number' ? res.statusCode : null,\n durationMs: Date.now() - started,\n requestBytes,\n responseBytes,\n requestHeaders: toHeaderRecord(req.headers),\n responseHeaders: toHeaderRecord(typeof res.getHeaders === 'function' ? res.getHeaders() : {}),\n requestBodyPreview: requestPreview,\n responseBodyPreview: responsePreview,\n requestBodyTruncated: state.options.maxBodyBytes > 0 && requestPreview.length >= state.options.maxBodyBytes,\n responseBodyTruncated: state.options.maxBodyBytes > 0 && responsePreview.length >= state.options.maxBodyBytes,\n droppedBeforeEvent: state.droppedCount,\n traceId,\n correlationId: req.headers && typeof req.headers['x-saptools-trace-id'] === 'string' ? req.headers['x-saptools-trace-id'] : null\n });\n };\n res.once('finish', finish);\n res.once('close', finish);\n };\n const patchEmit = (serverPrototype) => {\n if (!serverPrototype || serverPrototype.emit.__saptoolsCfLiveTracePatched) return undefined;\n const original = serverPrototype.emit;\n const patched = function patchedServerEmit(eventName, ...args) {\n if (eventName === 'request') observe(args[0], args[1]);\n return original.apply(this, [eventName, ...args]);\n };\n patched.__saptoolsCfLiveTracePatched = true;\n serverPrototype.emit = patched;\n return original;\n };\n const toTransportLimit = (value) => {\n const numeric = Number(value);\n return Number.isFinite(numeric) && numeric > 0 ? Math.floor(numeric) : 0;\n };\n const limitPreview = (event, previewKey, truncatedKey, maxChars) => {\n const preview = event[previewKey];\n if (maxChars <= 0 || typeof preview !== 'string' || preview.length <= maxChars) return event;\n return { ...event, [previewKey]: preview.slice(0, maxChars), [truncatedKey]: true };\n };\n const eventForDrain = (event, maxChars) => {\n if (!event || typeof event !== 'object') return event;\n let output = { ...event };\n output = limitPreview(output, 'requestBodyPreview', 'requestBodyTruncated', maxChars);\n output = limitPreview(output, 'responseBodyPreview', 'responseBodyTruncated', maxChars);\n return output;\n };\n const api = {\n version: runtimeVersion,\n async install(options) {\n state.options = { ...state.options, ...options };\n if (!state.installed) {\n if (!BufferCtor) {\n const bufferModule = await loadModule('buffer');\n BufferCtor = bufferModule && bufferModule.Buffer ? bufferModule.Buffer : BufferCtor;\n }\n const http = await loadModule('http');\n const https = await loadModule('https');\n state.originals.httpServerEmit = patchEmit(http && http.Server && http.Server.prototype);\n state.originals.httpsServerEmit = patchEmit(https && https.Server && https.Server.prototype);\n state.installed = true;\n }\n state.enabled = true;\n return api.status();\n },\n disable() {\n state.enabled = false;\n return api.status();\n },\n drainEvents(maxCount, maxTransportBodyBytes) {\n const count = Math.max(0, Math.min(Number(maxCount) || 0, state.queue.length));\n const transportLimit = toTransportLimit(maxTransportBodyBytes);\n const events = state.queue.splice(0, count).map((event) => eventForDrain(event, transportLimit));\n return { events, droppedCount: state.droppedCount, queueSize: state.queue.length };\n },\n status() {\n return { installed: state.installed, enabled: state.enabled, queueSize: state.queue.length, droppedCount: state.droppedCount, maxEvents: state.options.maxEvents };\n },\n uninstall() {\n state.enabled = false;\n const requireFn = loadRequire();\n if (requireFn) {\n const http = requireFn('http');\n const https = requireFn('https');\n if (state.originals.httpServerEmit && http && http.Server) http.Server.prototype.emit = state.originals.httpServerEmit;\n if (state.originals.httpsServerEmit && https && https.Server) https.Server.prototype.emit = state.originals.httpsServerEmit;\n }\n state.installed = false;\n return api.status();\n }\n };\n globalThis[name] = api;\n return api;\n})()\n`;\n\nexport function buildInstallExpression(options: RuntimeInstallOptions): string {\n return `${CF_LIVE_TRACE_RUNTIME_SOURCE}.install(${JSON.stringify(options)})`;\n}\n\nexport function buildDrainExpression(maxCount: number, maxTransportBodyBytes: number): string {\n return `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.drainEvents(${String(maxCount)}, ${String(maxTransportBodyBytes)}) ?? { events: [], droppedCount: 0, queueSize: 0 }`;\n}\n\nexport function buildStopExpression(options: StopExpressionOptions): string {\n return options.uninstallRuntimeHook\n ? `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.uninstall() ?? { installed: false, enabled: false }`\n : `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.disable() ?? { installed: false, enabled: false }`;\n}\n","import type { LiveTraceEvent, LiveTraceUrlSummary } from \"./types.js\";\n\ntype StatusBucket = \"2xx\" | \"3xx\" | \"4xx\" | \"5xx\" | \"unknown\";\n\ninterface MutableSummary {\n readonly normalizedUrl: string;\n readonly displayUrl: string;\n readonly methods: Set<string>;\n totalCount: number;\n readonly statusCounts: Record<StatusBucket, number>;\n latestStatus: number | null;\n latestDurationMs: number | null;\n latestSeenAt: string;\n}\n\nexport function buildUrlSummaries(events: readonly LiveTraceEvent[]): LiveTraceUrlSummary[] {\n const summaries = new Map<string, MutableSummary>();\n for (const event of events) {\n const normalizedUrl = normalizeEventUrl(event);\n const current = summaries.get(normalizedUrl) ?? createSummary(normalizedUrl);\n updateSummary(current, event);\n summaries.set(normalizedUrl, current);\n }\n return [...summaries.values()]\n .map(toImmutableSummary)\n .sort((left, right) => right.latestSeenAt.localeCompare(left.latestSeenAt));\n}\n\nexport function normalizeEventUrl(event: LiveTraceEvent): string {\n const candidate = event.normalizedUrl.length > 0 ? event.normalizedUrl : event.url.length > 0 ? event.url : event.path;\n return normalizeUrl(candidate);\n}\n\nfunction updateSummary(summary: MutableSummary, event: LiveTraceEvent): void {\n summary.methods.add(event.method);\n summary.totalCount += 1;\n summary.statusCounts[toStatusBucket(event.status)] += 1;\n if (event.timestamp >= summary.latestSeenAt) {\n summary.latestStatus = event.status;\n summary.latestDurationMs = event.durationMs;\n summary.latestSeenAt = event.timestamp;\n }\n}\n\nfunction normalizeUrl(rawUrl: string): string {\n if (rawUrl.trim().length === 0) {\n return rawUrl;\n }\n try {\n const parsed = new URL(rawUrl, \"https://saptools.local\");\n return `${parsed.pathname}${parsed.search}`;\n } catch {\n return rawUrl;\n }\n}\n\nfunction createSummary(normalizedUrl: string): MutableSummary {\n return {\n normalizedUrl,\n displayUrl: normalizedUrl,\n methods: new Set<string>(),\n totalCount: 0,\n statusCounts: { \"2xx\": 0, \"3xx\": 0, \"4xx\": 0, \"5xx\": 0, unknown: 0 },\n latestStatus: null,\n latestDurationMs: null,\n latestSeenAt: \"\",\n };\n}\n\nfunction toImmutableSummary(summary: MutableSummary): LiveTraceUrlSummary {\n return {\n normalizedUrl: summary.normalizedUrl,\n displayUrl: summary.displayUrl,\n methods: [...summary.methods].sort(),\n totalCount: summary.totalCount,\n statusCounts: { ...summary.statusCounts },\n latestStatus: summary.latestStatus,\n latestDurationMs: summary.latestDurationMs,\n latestSeenAt: summary.latestSeenAt,\n };\n}\n\nfunction toStatusBucket(status: number | null): StatusBucket {\n if (status === null) {\n return \"unknown\";\n }\n if (status >= 200 && status < 300) {\n return \"2xx\";\n }\n if (status >= 300 && status < 400) {\n return \"3xx\";\n }\n if (status >= 400 && status < 500) {\n return \"4xx\";\n }\n if (status >= 500 && status < 600) {\n return \"5xx\";\n }\n return \"unknown\";\n}\n","import { ensureSshEnabled, openInspectorTunnel, prepareCfSession, startNodeInspector } from \"./cf.js\";\nimport { connectRuntimeInspector } from \"./inspector.js\";\nimport { parseDrainResult } from \"./payload.js\";\nimport { buildDrainExpression, buildInstallExpression, buildStopExpression } from \"./runtime-source.js\";\nimport { buildUrlSummaries } from \"./summary.js\";\nimport type {\n CfLiveTraceTarget,\n InspectorStartupResult,\n InspectorRuntimeClient,\n LiveTraceEvent,\n LiveTraceStartOptions,\n LiveTraceStateEvent,\n LiveTraceStopOptions,\n TunnelOpenResult,\n} from \"./types.js\";\n\nexport interface LiveTraceSessionOptions {\n readonly target: CfLiveTraceTarget;\n readonly onState?: (event: LiveTraceStateEvent) => void;\n readonly onEvents?: (events: readonly LiveTraceEvent[]) => void;\n readonly onSummary?: (summary: ReturnType<typeof buildUrlSummaries>) => void;\n readonly onLog?: (message: string) => void;\n}\n\nexport interface LiveTraceDependencies {\n prepareCfSession(target: CfLiveTraceTarget): Promise<void>;\n ensureSshEnabled(target: CfLiveTraceTarget): Promise<void>;\n tryStartNodeInspector(target: CfLiveTraceTarget): Promise<boolean | InspectorStartupResult>;\n openInspectorTunnel(target: CfLiveTraceTarget): Promise<TunnelOpenResult>;\n connectInspector(localPort: number): Promise<InspectorRuntimeClient>;\n setInterval(callback: () => void, ms: number): NodeJS.Timeout;\n clearInterval(handle: NodeJS.Timeout): void;\n}\n\nconst DRAIN_INTERVAL_MS = 250;\nconst DRAIN_BATCH_SIZE = 50;\nconst RUNTIME_QUEUE_SIZE = 1000;\nconst CONTROL_EVALUATE_TIMEOUT_MS = 5000;\nconst DRAIN_EVALUATE_TIMEOUT_MS = 10000;\nconst DRAIN_TIMEOUT_RETRY_LIMIT = 3;\nconst DRAIN_TRANSPORT_BODY_LIMIT = 20_000;\n\nconst defaultDependencies: LiveTraceDependencies = {\n prepareCfSession,\n ensureSshEnabled,\n tryStartNodeInspector: startNodeInspector,\n openInspectorTunnel,\n connectInspector: connectRuntimeInspector,\n setInterval,\n clearInterval,\n};\n\nexport class LiveTraceSession {\n private readonly dependencies: LiveTraceDependencies;\n private readonly events: LiveTraceEvent[] = [];\n private consecutiveDrainTimeouts = 0;\n private drainInFlight = false;\n private inspectorClient: InspectorRuntimeClient | undefined;\n private pollTimer: NodeJS.Timeout | undefined;\n private state: LiveTraceStateEvent[\"state\"] = \"idle\";\n private stopRequested = false;\n private tunnelHandle: { readonly localPort: number; readonly stop: () => void } | undefined;\n\n public constructor(\n private readonly options: LiveTraceSessionOptions,\n dependencies: Partial<LiveTraceDependencies> = {},\n ) {\n this.dependencies = { ...defaultDependencies, ...dependencies };\n }\n\n public async start(options: LiveTraceStartOptions = {}): Promise<void> {\n if (this.isRunning()) {\n return;\n }\n this.stopRequested = false;\n await this.startRuntimeTrace(resolveStartOptions(options));\n }\n\n public async stop(options: LiveTraceStopOptions): Promise<void> {\n this.stopRequested = true;\n if (!this.isRunning()) {\n this.postState(\"stopped\", `Trace stopped (${options.reason}).`, false, false);\n return;\n }\n const hadRuntimeHook = this.inspectorClient !== undefined;\n this.postState(\"stopping\", `Stopping trace (${options.reason}).`, hadRuntimeHook, hadRuntimeHook);\n const uninstalled = await this.stopRuntimeTrace(options.uninstallRuntimeHook);\n this.postState(\"stopped\", `Trace stopped (${options.reason}).`, false, hadRuntimeHook && !uninstalled);\n }\n\n public isRunning(): boolean {\n return [\"preparing\", \"enabling-ssh\", \"starting-inspector\", \"opening-tunnel\", \"injecting\", \"streaming\", \"stopping\"].includes(this.state);\n }\n\n private async startRuntimeTrace(options: Required<LiveTraceStartOptions>): Promise<void> {\n try {\n this.postState(\"preparing\", \"Preparing Cloud Foundry session.\", false, false);\n await this.dependencies.prepareCfSession(this.options.target);\n if (this.shouldStop()) {\n return;\n }\n await this.startInspector(options);\n } catch (error) {\n this.log(`Live Trace startup failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false);\n const startupError = toStartupError(error);\n if (!this.shouldStop()) {\n this.postState(\"error\", startupError.stateMessage, false, false);\n }\n throw startupError;\n }\n }\n\n private async startInspector(options: Required<LiveTraceStartOptions>): Promise<void> {\n this.postState(\"enabling-ssh\", \"Ensuring CF SSH access.\", false, false);\n await this.dependencies.ensureSshEnabled(this.options.target);\n if (this.shouldStop()) {\n return;\n }\n this.postState(\"starting-inspector\", \"Requesting Node Inspector startup.\", false, false);\n this.reportInspectorStartup(await this.dependencies.tryStartNodeInspector(this.options.target));\n if (this.shouldStop()) {\n return;\n }\n this.postState(\"opening-tunnel\", \"Opening Node Inspector tunnel.\", false, false);\n const tunnel = await this.dependencies.openInspectorTunnel(this.options.target);\n await this.attachInspector(tunnel, options);\n }\n\n private async attachInspector(tunnel: TunnelOpenResult, options: Required<LiveTraceStartOptions>): Promise<void> {\n if (this.shouldStop()) {\n stopLateTunnel(tunnel);\n return;\n }\n if (tunnel.status !== \"ready\") {\n throw new LiveTraceStartupError(\n \"Node Inspector is not reachable on 127.0.0.1:9229.\",\n \"Node Inspector is not reachable on 127.0.0.1:9229.\",\n );\n }\n this.tunnelHandle = tunnel.handle;\n this.inspectorClient = await this.dependencies.connectInspector(tunnel.handle.localPort);\n this.postState(\"injecting\", \"Installing runtime HTTP trace hook.\", false, false);\n await this.installRuntimeHook(options);\n this.startPolling(options.maxBodyBytes);\n this.postState(\"streaming\", \"Streaming runtime HTTP trace events.\", true, false);\n }\n\n private async installRuntimeHook(options: Required<LiveTraceStartOptions>): Promise<void> {\n await this.requireInspector().evaluate(buildInstallExpression({\n appId: this.options.target.app,\n instance: String(this.options.target.instanceIndex ?? 0),\n captureHeaders: options.captureHeaders,\n captureRequestBody: options.captureRequestBody,\n captureResponseBody: options.captureResponseBody,\n maxBodyBytes: options.maxBodyBytes,\n maxEvents: options.runtimeQueueSize,\n }), CONTROL_EVALUATE_TIMEOUT_MS);\n }\n\n private startPolling(maxBodyBytes: number): void {\n this.stopPolling();\n this.consecutiveDrainTimeouts = 0;\n this.pollTimer = this.dependencies.setInterval(() => {\n void this.drainTraceEvents(maxBodyBytes);\n }, DRAIN_INTERVAL_MS);\n }\n\n private async drainTraceEvents(maxBodyBytes: number): Promise<void> {\n if (this.drainInFlight || this.inspectorClient === undefined || this.state !== \"streaming\") {\n return;\n }\n this.drainInFlight = true;\n try {\n const payload = await this.inspectorClient.evaluate(\n buildDrainExpression(DRAIN_BATCH_SIZE, resolveDrainTransportBodyLimit(maxBodyBytes)),\n DRAIN_EVALUATE_TIMEOUT_MS,\n );\n this.consecutiveDrainTimeouts = 0;\n this.publishDrainedEvents(payload, maxBodyBytes);\n } catch (error) {\n await this.handleDrainFailure(error);\n } finally {\n this.drainInFlight = false;\n }\n }\n\n private publishDrainedEvents(payload: unknown, maxBodyBytes: number): void {\n const drained = parseDrainResult(payload, { appId: this.options.target.app, maxBodyBytes });\n if (drained.events.length === 0) {\n return;\n }\n this.events.push(...drained.events);\n this.events.splice(0, Math.max(0, this.events.length - RUNTIME_QUEUE_SIZE));\n this.options.onEvents?.(drained.events);\n this.options.onSummary?.(buildUrlSummaries(this.events));\n }\n\n private async handleDrainFailure(error: unknown): Promise<void> {\n if (isEvaluateTimeout(error)) {\n this.consecutiveDrainTimeouts += 1;\n if (this.consecutiveDrainTimeouts < DRAIN_TIMEOUT_RETRY_LIMIT) {\n this.log(`Live Trace drain timed out for ${this.options.target.app}; retrying (${String(this.consecutiveDrainTimeouts)}/${String(DRAIN_TIMEOUT_RETRY_LIMIT)}).`);\n return;\n }\n }\n this.log(`Live Trace stream failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false);\n this.postState(\"error\", \"Runtime HTTP trace connection was lost.\", false, true);\n }\n\n private async stopRuntimeTrace(uninstallRuntimeHook: boolean): Promise<boolean> {\n this.stopPolling();\n this.consecutiveDrainTimeouts = 0;\n const uninstalled = await this.stopInspectorHook(uninstallRuntimeHook);\n await this.closeInspectorClient();\n this.stopTunnel();\n return uninstalled;\n }\n\n private async closeInspectorClient(): Promise<void> {\n const client = this.inspectorClient;\n this.inspectorClient = undefined;\n try {\n await client?.close();\n } catch (error) {\n this.log(`Live Trace inspector close failed for ${this.options.target.app}: ${formatError(error)}`);\n }\n }\n\n private stopTunnel(): void {\n const tunnel = this.tunnelHandle;\n this.tunnelHandle = undefined;\n try {\n tunnel?.stop();\n } catch (error) {\n this.log(`Live Trace tunnel cleanup failed for ${this.options.target.app}: ${formatError(error)}`);\n }\n }\n\n private async stopInspectorHook(uninstallRuntimeHook: boolean): Promise<boolean> {\n if (this.inspectorClient === undefined) {\n return true;\n }\n try {\n await this.inspectorClient.evaluate(buildStopExpression({ uninstallRuntimeHook }), CONTROL_EVALUATE_TIMEOUT_MS);\n return uninstallRuntimeHook;\n } catch (error) {\n this.log(`Live Trace cleanup failed for ${this.options.target.app}: ${formatError(error)}`);\n return false;\n }\n }\n\n private stopPolling(): void {\n if (this.pollTimer === undefined) {\n return;\n }\n this.dependencies.clearInterval(this.pollTimer);\n this.pollTimer = undefined;\n }\n\n private postState(state: LiveTraceStateEvent[\"state\"], message: string, runtimeHookInstalled: boolean, runtimeHookMayRemain: boolean): void {\n this.state = state;\n this.options.onState?.({\n state,\n app: this.options.target.app,\n instance: String(this.options.target.instanceIndex ?? 0),\n message,\n runtimeHookInstalled,\n runtimeHookMayRemain,\n });\n }\n\n private requireInspector(): InspectorRuntimeClient {\n if (this.inspectorClient === undefined) {\n throw new Error(\"Inspector client is not connected.\");\n }\n return this.inspectorClient;\n }\n\n private shouldStop(): boolean {\n return this.stopRequested;\n }\n\n private log(message: string): void {\n this.options.onLog?.(message);\n }\n\n private reportInspectorStartup(result: boolean | InspectorStartupResult): void {\n const normalized = normalizeInspectorStartupResult(result);\n if (normalized.status === \"ready\") {\n return;\n }\n const detail = normalized.detail === undefined ? \"\" : `: ${normalized.detail}`;\n this.log(`Node Inspector startup was not confirmed for ${this.options.target.app}${detail}`);\n }\n}\n\nclass LiveTraceStartupError extends Error {\n public constructor(\n message: string,\n public readonly stateMessage: string,\n cause?: unknown,\n ) {\n super(message, cause === undefined ? undefined : { cause });\n }\n}\n\nfunction resolveStartOptions(options: LiveTraceStartOptions): Required<LiveTraceStartOptions> {\n return {\n captureHeaders: options.captureHeaders ?? true,\n captureRequestBody: options.captureRequestBody ?? true,\n captureResponseBody: options.captureResponseBody ?? true,\n maxBodyBytes: options.maxBodyBytes ?? 4096,\n runtimeQueueSize: options.runtimeQueueSize ?? RUNTIME_QUEUE_SIZE,\n };\n}\n\nfunction stopLateTunnel(tunnel: TunnelOpenResult): void {\n if (tunnel.status === \"ready\") {\n tunnel.handle.stop();\n }\n}\n\nfunction resolveDrainTransportBodyLimit(maxBodyBytes: number): number {\n return maxBodyBytes > 0 ? Math.min(maxBodyBytes, DRAIN_TRANSPORT_BODY_LIMIT) : DRAIN_TRANSPORT_BODY_LIMIT;\n}\n\nfunction isEvaluateTimeout(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(\"Runtime.evaluate timed out\");\n}\n\nfunction toStartupError(error: unknown): LiveTraceStartupError {\n if (error instanceof LiveTraceStartupError) {\n return error;\n }\n return new LiveTraceStartupError(\n \"Runtime HTTP trace could not be started.\",\n \"Runtime HTTP trace could not be started.\",\n error,\n );\n}\n\nfunction normalizeInspectorStartupResult(result: boolean | InspectorStartupResult): InspectorStartupResult {\n return typeof result === \"boolean\"\n ? { status: result ? \"ready\" : \"not-ready\" }\n : result;\n}\n\nfunction formatError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n","import { readCurrentCfTarget, type CurrentCfTarget, type CurrentCfTargetReadOptions } from \"../cf.js\";\nimport type { CfLiveTraceTarget, LiveTraceStartOptions } from \"../types.js\";\n\nexport type OutputFormat = \"ndjson\" | \"summary\" | \"json\";\n\nexport interface CliFlags {\n readonly region?: string;\n readonly apiEndpoint?: string;\n readonly org?: string;\n readonly space?: string;\n readonly app?: string;\n readonly email?: string;\n readonly password?: string;\n readonly instance?: string;\n readonly cfHome?: string;\n readonly cfCommand?: string;\n readonly duration?: string;\n readonly maxEvents?: string;\n readonly maxBodyBytes?: string;\n readonly captureHeaders?: boolean;\n readonly captureRequestBody?: boolean;\n readonly captureResponseBody?: boolean;\n readonly uninstallOnExit?: boolean;\n readonly format?: string;\n readonly quiet?: boolean;\n}\n\nexport interface RunOptions {\n readonly target: CfLiveTraceTarget;\n readonly trace: Required<LiveTraceStartOptions>;\n readonly limits: {\n readonly durationMs?: number;\n readonly maxEvents?: number;\n };\n readonly format: OutputFormat;\n readonly uninstallOnExit: boolean;\n readonly quiet: boolean;\n}\n\nexport function buildRunOptions(flags: CliFlags, env: Record<string, string | undefined>): RunOptions {\n requireRegionOrApi(flags);\n const target = buildTarget(flags, env);\n return {\n target,\n trace: {\n captureHeaders: flags.captureHeaders !== false,\n captureRequestBody: flags.captureRequestBody !== false,\n captureResponseBody: flags.captureResponseBody !== false,\n maxBodyBytes: parseBodyLimit(flags.maxBodyBytes),\n runtimeQueueSize: 1000,\n },\n limits: buildLimits(flags),\n format: parseFormat(flags.format),\n uninstallOnExit: flags.uninstallOnExit !== false,\n quiet: flags.quiet === true,\n };\n}\n\nexport async function buildRunOptionsWithCurrentTarget(\n flags: CliFlags,\n env: Record<string, string | undefined>,\n): Promise<RunOptions> {\n return buildRunOptions(await resolveCurrentTargetFlags(flags, env), env);\n}\n\nexport function parsePositiveInteger(raw: string | undefined, label: string): number | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const value = Number.parseInt(raw, 10);\n if (!Number.isInteger(value) || value <= 0 || String(value) !== raw.trim()) {\n throw new Error(`Invalid ${label}: \"${raw}\" — expected a positive integer.`);\n }\n return value;\n}\n\nasync function resolveCurrentTargetFlags(\n flags: CliFlags,\n env: Record<string, string | undefined>,\n): Promise<CliFlags> {\n if (!needsCurrentTarget(flags)) {\n return flags;\n }\n\n const current = await readCurrentCfTarget(currentCfContext(flags, env)).catch((error: unknown) => {\n throw new Error(\n \"No current CF target found. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\n { cause: error },\n );\n });\n if (current === undefined) {\n throw new Error(\n \"No current CF target found. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\n );\n }\n\n return {\n ...flags,\n ...currentApiFields(flags, current),\n org: textOrFallback(flags.org, current.orgName),\n space: textOrFallback(flags.space, current.spaceName),\n };\n}\n\nfunction currentCfContext(flags: CliFlags, env: Record<string, string | undefined>): CurrentCfTargetReadOptions | undefined {\n const command = flags.cfCommand ?? env[\"CF_LIVE_TRACE_CF_BIN\"];\n const context: CurrentCfTargetReadOptions = {\n ...(command === undefined ? {} : { command }),\n ...(flags.cfHome === undefined ? {} : { env: { CF_HOME: flags.cfHome } }),\n };\n return context.command === undefined && context.env === undefined ? undefined : context;\n}\n\nfunction currentApiFields(\n flags: CliFlags,\n current: CurrentCfTarget,\n): Pick<CliFlags, \"apiEndpoint\" | \"region\"> {\n if (hasText(flags.region) || hasText(flags.apiEndpoint)) {\n return {};\n }\n return current.regionKey === undefined\n ? { apiEndpoint: current.apiEndpoint }\n : { region: current.regionKey };\n}\n\nfunction needsCurrentTarget(flags: CliFlags): boolean {\n return (!hasText(flags.region) && !hasText(flags.apiEndpoint)) || !hasText(flags.org) || !hasText(flags.space);\n}\n\nfunction hasText(value: string | undefined): boolean {\n return value !== undefined && value.trim().length > 0;\n}\n\nfunction textOrFallback(value: string | undefined, fallback: string): string {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? fallback : trimmed;\n}\n\nfunction buildTarget(flags: CliFlags, env: Record<string, string | undefined>): CfLiveTraceTarget {\n const apiPart = flags.apiEndpoint === undefined ? { region: requireText(flags.region, \"--region\") } : { apiEndpoint: requireText(flags.apiEndpoint, \"--api-endpoint\") };\n return {\n ...apiPart,\n org: requireText(flags.org, \"--org\"),\n space: requireText(flags.space, \"--space\"),\n app: requireText(flags.app, \"--app\"),\n email: resolveCredential(flags.email, env, \"SAP_EMAIL\"),\n password: resolveCredential(flags.password, env, \"SAP_PASSWORD\"),\n instanceIndex: parseInstanceIndex(flags.instance),\n ...(flags.cfHome === undefined ? {} : { cfHomeDir: requireText(flags.cfHome, \"--cf-home\") }),\n ...(flags.cfCommand === undefined ? {} : { command: requireText(flags.cfCommand, \"--cf-command\") }),\n };\n}\n\nfunction buildLimits(flags: CliFlags): RunOptions[\"limits\"] {\n const duration = parsePositiveInteger(flags.duration, \"--duration\");\n const maxEvents = parsePositiveInteger(flags.maxEvents, \"--max-events\");\n return {\n ...(duration === undefined ? {} : { durationMs: duration * 1000 }),\n ...(maxEvents === undefined ? {} : { maxEvents }),\n };\n}\n\nfunction requireRegionOrApi(flags: CliFlags): void {\n const hasRegion = flags.region !== undefined && flags.region.trim().length > 0;\n const hasApi = flags.apiEndpoint !== undefined && flags.apiEndpoint.trim().length > 0;\n if (!hasRegion && !hasApi) {\n throw new Error(\"Either --region or --api-endpoint is required.\");\n }\n}\n\nfunction requireText(value: string | undefined, label: string): string {\n if (value === undefined || value.trim().length === 0) {\n throw new Error(`${label} is required.`);\n }\n return value.trim();\n}\n\nfunction resolveCredential(value: string | undefined, env: Record<string, string | undefined>, envName: string): string {\n const directValue = value?.trim();\n if (directValue !== undefined && directValue.length > 0) {\n return directValue;\n }\n const envValue = env[envName]?.trim();\n if (envValue !== undefined && envValue.length > 0) {\n return envValue;\n }\n throw new Error(`Missing required environment variable: ${envName}`);\n}\n\nfunction parseInstanceIndex(value: string | undefined): number {\n const parsed = value === undefined ? undefined : parseNonNegativeInteger(value, \"--instance\");\n return parsed ?? 0;\n}\n\nfunction parseBodyLimit(value: string | undefined): number {\n if (value === undefined) {\n return 4096;\n }\n return parseNonNegativeInteger(value, \"--max-body-bytes\");\n}\n\nfunction parseNonNegativeInteger(raw: string, label: string): number {\n const value = Number.parseInt(raw, 10);\n if (!Number.isInteger(value) || value < 0 || String(value) !== raw.trim()) {\n throw new Error(`Invalid ${label}: \"${raw}\" — expected a non-negative integer.`);\n }\n return value;\n}\n\nfunction parseFormat(value: string | undefined): OutputFormat {\n if (value === undefined || value === \"ndjson\") {\n return \"ndjson\";\n }\n if (value === \"summary\" || value === \"json\") {\n return value;\n }\n throw new Error(`Invalid --format: \"${value}\" — expected ndjson, summary, or json.`);\n}\n","import process from \"node:process\";\n\nimport type { LiveTraceEvent, LiveTraceStateEvent } from \"../types.js\";\n\nexport function writeJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nexport function writeJsonLine(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value)}\\n`);\n}\n\nexport function writeProgress(event: LiveTraceStateEvent): void {\n process.stderr.write(`[cf-live-trace] ${event.state}: ${event.message}\\n`);\n}\n\nexport function writeLog(message: string): void {\n process.stderr.write(`[cf-live-trace] ${message}\\n`);\n}\n\nexport function writeSummaryLine(event: LiveTraceEvent): void {\n const status = event.status === null ? \"-\" : String(event.status);\n const duration = event.durationMs === null ? \"-\" : `${event.durationMs.toString()}ms`;\n process.stdout.write(`${event.timestamp} ${event.method} ${event.normalizedUrl} ${status} ${duration}\\n`);\n}\n"],"mappings":"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","names":["process","process","isRecord","buildRunOptions","process","process","process"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/cli/program.ts","../src/cf.ts","../src/inspector.ts","../src/preview.ts","../src/payload.ts","../src/runtime-source.ts","../src/summary.ts","../src/session.ts","../src/cli/options.ts","../src/cli/output.ts"],"sourcesContent":["import process from \"node:process\";\n\nimport { main } from \"./cli/program.js\";\n\ntry {\n await main(process.argv);\n} catch (error) {\n process.stderr.write(`[cf-live-trace] error: ${formatCliError(error)}\\n`);\n process.exitCode = 1;\n}\n\nfunction formatCliError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n","import process from \"node:process\";\n\nimport { Command } from \"commander\";\n\nimport { createTemporaryCfHome, removeTemporaryCfHome } from \"../cf.js\";\nimport { LiveTraceSession } from \"../session.js\";\nimport type { LiveTraceEvent, LiveTraceStateEvent, LiveTraceStopReason } from \"../types.js\";\n\nimport { buildRunOptionsWithCurrentTarget, type CliFlags, type RunOptions } from \"./options.js\";\nimport { writeJson, writeJsonLine, writeLog, writeProgress, writeSummaryLine } from \"./output.js\";\n\nexport async function main(argv: readonly string[]): Promise<void> {\n const program = new Command();\n program\n .name(\"cf-live-trace\")\n .description(\"Inject a runtime HTTP trace hook into a Cloud Foundry Node.js app and stream request/response events\")\n .option(\"-r, --region <key>\", \"CF region key (default: current cf target)\")\n .option(\"--api-endpoint <url>\", \"Explicit CF API endpoint\")\n .option(\"-o, --org <name>\", \"CF org name (default: current cf target)\")\n .option(\"-s, --space <name>\", \"CF space name (default: current cf target)\")\n .requiredOption(\"-a, --app <name>\", \"CF app name\")\n .option(\"--email <value>\", \"SAP email (default: SAP_EMAIL)\")\n .option(\"--password <value>\", \"SAP password (default: SAP_PASSWORD)\")\n .option(\"-i, --instance <index>\", \"CF app instance index (default: 0)\")\n .option(\"--cf-home <dir>\", \"Use an existing CF_HOME instead of a temporary one\")\n .option(\"--cf-command <path>\", \"CF CLI executable or test shim\")\n .option(\"--duration <seconds>\", \"Stop after N seconds\")\n .option(\"--max-events <count>\", \"Stop after N trace events\")\n .option(\"--max-body-bytes <bytes>\", \"Maximum request/response preview bytes; 0 keeps unlimited previews locally\", \"4096\")\n .option(\"--no-capture-headers\", \"Do not capture request/response headers\")\n .option(\"--no-capture-request-body\", \"Do not capture request body previews\")\n .option(\"--no-capture-response-body\", \"Do not capture response body previews\")\n .option(\"--no-uninstall-on-exit\", \"Disable the runtime hook instead of uninstalling it on exit\")\n .option(\"--format <format>\", \"Output format: ndjson, summary, json\", \"ndjson\")\n .option(\"--quiet\", \"Suppress progress messages on stderr\")\n .action(async (flags: CliFlags): Promise<void> => {\n await runTraceCommand(await buildRunOptionsWithCurrentTarget(flags, process.env));\n });\n\n await program.parseAsync([...argv]);\n}\n\nexport async function runTraceCommand(options: RunOptions): Promise<void> {\n const cfHome = await resolveCfHome(options);\n try {\n const events: LiveTraceEvent[] = [];\n const eventLimit = createEventLimit(options);\n const runtimeError = createRuntimeErrorStopWaiter();\n const session = new LiveTraceSession({\n target: { ...options.target, cfHomeDir: cfHome.path },\n onState: (event) => {\n if (!options.quiet) {\n writeProgress(event);\n }\n runtimeError.report(event);\n },\n onLog: (message) => {\n if (!options.quiet) {\n writeLog(message);\n }\n },\n onEvents: (batch) => {\n handleEvents(batch, options, events);\n eventLimit.check(events.length);\n },\n });\n await runUntilStopped(session, options, eventLimit, runtimeError);\n if (options.format === \"json\") {\n writeJson({ events });\n }\n } finally {\n await cfHome.dispose();\n }\n}\n\nfunction handleEvents(batch: readonly LiveTraceEvent[], options: RunOptions, events: LiveTraceEvent[]): void {\n for (const event of batch) {\n events.push(event);\n if (options.format === \"ndjson\") {\n writeJsonLine(event);\n }\n if (options.format === \"summary\") {\n writeSummaryLine(event);\n }\n }\n}\n\nasync function runUntilStopped(\n session: LiveTraceSession,\n options: RunOptions,\n eventLimit: StopWaiter & { readonly check: (count: number) => void },\n runtimeError: RuntimeErrorStopWaiter,\n): Promise<void> {\n const abort = createAbortPromise();\n const duration = createDurationStopWaiter(options.limits.durationMs);\n let stopReason: LiveTraceStopReason = \"user\";\n let failed = false;\n try {\n await session.start(options.trace);\n stopReason = await waitForStop([abort, eventLimit, duration, runtimeError]);\n } catch (error) {\n failed = true;\n throw error;\n } finally {\n abort.cleanup();\n duration.cleanup();\n eventLimit.cleanup();\n runtimeError.cleanup();\n await session.stop({ uninstallRuntimeHook: options.uninstallOnExit, reason: failed ? \"error\" : stopReason });\n }\n}\n\ninterface StopWaiter {\n readonly promise: Promise<LiveTraceStopReason>;\n cleanup(): void;\n}\n\ninterface RuntimeErrorStopWaiter extends StopWaiter {\n report(event: LiveTraceStateEvent): void;\n}\n\nasync function waitForStop(waiters: readonly StopWaiter[]): Promise<LiveTraceStopReason> {\n return await Promise.race(waiters.map((waiter) => waiter.promise));\n}\n\nfunction createDurationStopWaiter(durationMs: number | undefined): StopWaiter {\n if (durationMs === undefined) {\n return createNeverStopWaiter();\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const promise = new Promise<LiveTraceStopReason>((resolve) => {\n timer = setTimeout(() => {\n resolve(\"duration\");\n }, durationMs);\n });\n return {\n promise,\n cleanup: (): void => {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n },\n };\n}\n\nfunction createAbortPromise(): { readonly promise: Promise<LiveTraceStopReason>; readonly cleanup: () => void } {\n let resolveStop: (reason: LiveTraceStopReason) => void = () => {\n return;\n };\n const promise = new Promise<LiveTraceStopReason>((resolve) => {\n resolveStop = resolve;\n });\n const onSignal = (): void => {\n resolveStop(\"user\");\n };\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n return {\n promise,\n cleanup: (): void => {\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n },\n };\n}\n\nfunction createNeverStopWaiter(): StopWaiter {\n return {\n promise: new Promise<LiveTraceStopReason>(() => {\n return;\n }),\n cleanup: (): void => {\n return;\n },\n };\n}\n\nfunction createRuntimeErrorStopWaiter(): RuntimeErrorStopWaiter {\n let hasStreamed = false;\n let settled = false;\n let rejectStop: (error: Error) => void = () => {\n return;\n };\n const promise = new Promise<LiveTraceStopReason>((_resolve, reject) => {\n rejectStop = reject;\n });\n promise.catch(() => {\n return;\n });\n return {\n promise,\n report: (event): void => {\n if (event.state === \"streaming\") {\n hasStreamed = true;\n return;\n }\n if (event.state !== \"error\" || !hasStreamed || settled) {\n return;\n }\n settled = true;\n rejectStop(new Error(event.message));\n },\n cleanup: (): void => {\n settled = true;\n },\n };\n}\n\nfunction createEventLimit(options: RunOptions): {\n readonly promise: Promise<LiveTraceStopReason>;\n readonly check: (count: number) => void;\n readonly cleanup: () => void;\n} {\n if (options.limits.maxEvents === undefined) {\n return {\n ...createNeverStopWaiter(),\n check: (): void => {\n return;\n },\n };\n }\n let resolveLimit: (reason: LiveTraceStopReason) => void = () => {\n return;\n };\n const promise = new Promise<LiveTraceStopReason>((resolve) => {\n resolveLimit = resolve;\n });\n return {\n promise,\n check: (count): void => {\n if (options.limits.maxEvents !== undefined && count >= options.limits.maxEvents) {\n resolveLimit(\"max-events\");\n }\n },\n cleanup: (): void => {\n return;\n },\n };\n}\n\nasync function resolveCfHome(options: RunOptions): Promise<{ readonly path: string; readonly dispose: () => Promise<void> }> {\n if (options.target.cfHomeDir !== undefined) {\n return {\n path: options.target.cfHomeDir,\n dispose: (): Promise<void> => Promise.resolve(),\n };\n }\n const path = await createTemporaryCfHome();\n return {\n path,\n dispose: async (): Promise<void> => {\n await removeTemporaryCfHome(path);\n },\n };\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { connect as netConnect, createServer } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nimport type { CfLiveTraceTarget, InspectorStartupResult, PortForwardHandle, TunnelOpenResult } from \"./types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CF_MAX_BUFFER_BYTES = 8 * 1024 * 1024;\nconst CF_COMMAND_TIMEOUT_MS = 180_000;\nconst CF_SSH_READY_TIMEOUT_MS = 60_000;\nconst INSPECTOR_SIGNAL_TIMEOUT_MS = 15_000;\nconst INSPECTOR_REMOTE_HOST = \"127.0.0.1\";\nconst INSPECTOR_REMOTE_PORT = 9229;\nconst TUNNEL_KEEPALIVE_SECONDS = 6 * 60 * 60;\nconst TUNNEL_READY_TIMEOUT_MS = 20_000;\nconst TUNNEL_READY_POLL_MS = 200;\n\nexport interface RunCfOptions {\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly envOverrides?: Record<string, string>;\n readonly timeoutMs?: number;\n readonly redactor?: (message: string) => string;\n}\n\nexport interface CfDependencies {\n runCf(args: readonly string[], options: RunCfOptions): Promise<string>;\n}\n\nexport interface TunnelDependencies {\n allocatePort(): Promise<number>;\n spawnPortForward(params: PortForwardParams): PortForwardHandle;\n waitForLocalPort(port: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean>;\n}\n\nexport interface PortForwardParams {\n readonly appName: string;\n readonly localPort: number;\n readonly remoteHost: string;\n readonly remotePort: number;\n readonly keepAliveSeconds: number;\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly instanceIndex?: number;\n}\n\nexport interface InspectorTunnelTarget {\n readonly app?: string;\n readonly appName?: string;\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly instanceIndex?: number;\n}\n\nexport async function createTemporaryCfHome(): Promise<string> {\n return await mkdtemp(join(tmpdir(), \"saptools-cf-live-trace-\"));\n}\n\nexport async function removeTemporaryCfHome(cfHomeDir: string): Promise<void> {\n await rm(cfHomeDir, { recursive: true, force: true });\n}\n\nexport async function prepareCfSession(\n target: CfLiveTraceTarget,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<void> {\n const apiEndpoint = resolveApiEndpoint(target);\n const redactor = createSecretRedactor([target.email, target.password]);\n const baseOptions = buildRunOptions(target, redactor);\n await dependencies.runCf([\"api\", apiEndpoint], baseOptions);\n await dependencies.runCf([\"auth\"], {\n ...baseOptions,\n envOverrides: { CF_USERNAME: target.email, CF_PASSWORD: target.password },\n });\n await dependencies.runCf([\"target\", \"-o\", target.org, \"-s\", target.space], baseOptions);\n}\n\nexport async function ensureSshEnabled(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<void> {\n const redactor = createSecretRedactor([target.email, target.password]);\n const options = buildRunOptions(target, redactor);\n const status = await dependencies.runCf([\"ssh-enabled\", target.app], options);\n if (parseSshStatus(status) === \"enabled\") {\n return;\n }\n await dependencies.runCf([\"enable-ssh\", target.app], options);\n await dependencies.runCf([\"restart\", target.app], options);\n await dependencies.runCf(buildCfSshArgs(target.app, target.instanceIndex, [\"-c\", \"true\"]), {\n ...options,\n timeoutMs: CF_SSH_READY_TIMEOUT_MS,\n });\n}\n\nexport async function tryStartNodeInspector(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<boolean> {\n const result = await startNodeInspector(target, dependencies);\n return result.status === \"ready\";\n}\n\nexport async function startNodeInspector(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<InspectorStartupResult> {\n const redactor = createSecretRedactor([target.email, target.password]);\n try {\n const stdout = await dependencies.runCf(\n buildCfSshArgs(target.app, target.instanceIndex, [\"-c\", buildInspectorSignalCommand()]),\n { ...buildRunOptions(target, redactor), timeoutMs: INSPECTOR_SIGNAL_TIMEOUT_MS },\n );\n return hasInspectorReadyMarker(stdout)\n ? { status: \"ready\" }\n : { status: \"not-ready\", ...optionalDetail(summarizeInspectorStartupOutput(stdout)) };\n } catch (error) {\n return { status: \"not-ready\", ...optionalDetail(redactor(formatErrorMessage(error))) };\n }\n}\n\nexport async function openInspectorTunnel(\n target: InspectorTunnelTarget,\n dependencies: TunnelDependencies = defaultTunnelDependencies,\n): Promise<TunnelOpenResult> {\n const localPort = await dependencies.allocatePort();\n const handle = dependencies.spawnPortForward(buildPortForwardParams(target, localPort));\n const ready = await raceForwardReadiness(handle, dependencies);\n if (!ready) {\n handle.stop();\n return { status: \"not-reachable\" };\n }\n return { status: \"ready\", handle };\n}\n\nexport function buildCfSshArgs(appName: string, instanceIndex: number | undefined, tail: readonly string[]): string[] {\n const args = [\"ssh\", appName];\n if (instanceIndex !== undefined) {\n args.push(\"-i\", String(instanceIndex));\n }\n return [...args, ...tail];\n}\n\nexport function buildInspectorSignalCommand(): string {\n return INSPECTOR_SIGNAL_COMMAND;\n}\n\nexport function createSecretRedactor(secrets: readonly string[]): (message: string) => string {\n const values = secrets.map((secret) => secret.trim()).filter((secret) => secret.length > 0);\n return (message: string): string => values.reduce((current, secret) => current.split(secret).join(\"<redacted>\"), message);\n}\n\nexport async function runCfCommand(args: readonly string[], options: RunCfOptions): Promise<string> {\n const command = resolveCommand(options.command);\n try {\n const { stdout } = await execFileAsync(command.bin, [...command.argsPrefix, ...args], {\n env: buildCfEnv(options.cfHomeDir, options.envOverrides),\n maxBuffer: CF_MAX_BUFFER_BYTES,\n timeout: options.timeoutMs ?? CF_COMMAND_TIMEOUT_MS,\n });\n return stdout;\n } catch (error) {\n throw new Error(formatCfError(args, error, options.redactor), { cause: error });\n }\n}\n\nexport function spawnPortForward(params: PortForwardParams): PortForwardHandle {\n const command = resolveCommand(params.command);\n const forwardSpec = `${String(params.localPort)}:${params.remoteHost}:${String(params.remotePort)}`;\n const sshArgs = buildCfSshArgs(params.appName, params.instanceIndex, [\"-L\", forwardSpec, \"-c\", `sleep ${String(params.keepAliveSeconds)}`]);\n const child = spawn(command.bin, [...command.argsPrefix, ...sshArgs], {\n env: buildCfEnv(params.cfHomeDir),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n child.stdout.resume();\n child.stderr.resume();\n return {\n process: child,\n localPort: params.localPort,\n stop(): void {\n if (!child.killed) {\n child.kill();\n }\n },\n };\n}\n\nexport const defaultCfDependencies: CfDependencies = {\n runCf: runCfCommand,\n};\n\nexport const defaultTunnelDependencies: TunnelDependencies = {\n allocatePort: findFreePort,\n spawnPortForward,\n waitForLocalPort,\n};\n\nfunction buildRunOptions(target: Pick<CfLiveTraceTarget, \"cfHomeDir\" | \"command\">, redactor: (message: string) => string): RunCfOptions {\n return {\n ...(target.cfHomeDir === undefined ? {} : { cfHomeDir: target.cfHomeDir }),\n ...(target.command === undefined ? {} : { command: target.command }),\n redactor,\n };\n}\n\nfunction resolveApiEndpoint(target: Pick<CfLiveTraceTarget, \"apiEndpoint\" | \"region\">): string {\n if (target.apiEndpoint !== undefined && target.apiEndpoint.trim().length > 0) {\n return target.apiEndpoint.trim();\n }\n if (target.region === undefined) {\n throw new Error(\"CF region or apiEndpoint is required.\");\n }\n const endpoint = REGION_API_ENDPOINTS[target.region];\n if (endpoint === undefined) {\n throw new Error(`Unknown CF region: ${target.region}`);\n }\n return endpoint;\n}\n\nconst REGION_API_ENDPOINTS: Readonly<Record<string, string>> = {\n ae01: \"https://api.cf.ae01.hana.ondemand.com\",\n ap01: \"https://api.cf.ap01.hana.ondemand.com\",\n ap10: \"https://api.cf.ap10.hana.ondemand.com\",\n ap11: \"https://api.cf.ap11.hana.ondemand.com\",\n ap12: \"https://api.cf.ap12.hana.ondemand.com\",\n ap20: \"https://api.cf.ap20.hana.ondemand.com\",\n ap21: \"https://api.cf.ap21.hana.ondemand.com\",\n ap30: \"https://api.cf.ap30.hana.ondemand.com\",\n br10: \"https://api.cf.br10.hana.ondemand.com\",\n br20: \"https://api.cf.br20.hana.ondemand.com\",\n br30: \"https://api.cf.br30.hana.ondemand.com\",\n ca10: \"https://api.cf.ca10.hana.ondemand.com\",\n ca20: \"https://api.cf.ca20.hana.ondemand.com\",\n ch20: \"https://api.cf.ch20.hana.ondemand.com\",\n eu10: \"https://api.cf.eu10.hana.ondemand.com\",\n eu11: \"https://api.cf.eu11.hana.ondemand.com\",\n eu12: \"https://api.cf.eu12.hana.ondemand.com\",\n eu20: \"https://api.cf.eu20.hana.ondemand.com\",\n eu21: \"https://api.cf.eu21.hana.ondemand.com\",\n eu30: \"https://api.cf.eu30.hana.ondemand.com\",\n eu31: \"https://api.cf.eu31.hana.ondemand.com\",\n in30: \"https://api.cf.in30.hana.ondemand.com\",\n jp10: \"https://api.cf.jp10.hana.ondemand.com\",\n jp20: \"https://api.cf.jp20.hana.ondemand.com\",\n jp30: \"https://api.cf.jp30.hana.ondemand.com\",\n kr30: \"https://api.cf.kr30.hana.ondemand.com\",\n us10: \"https://api.cf.us10.hana.ondemand.com\",\n us11: \"https://api.cf.us11.hana.ondemand.com\",\n us20: \"https://api.cf.us20.hana.ondemand.com\",\n us21: \"https://api.cf.us21.hana.ondemand.com\",\n us30: \"https://api.cf.us30.hana.ondemand.com\",\n us31: \"https://api.cf.us31.hana.ondemand.com\",\n};\n\nfunction regionKeyForApiEndpoint(apiEndpoint: string): string | undefined {\n const normalized = normalizeApiEndpoint(apiEndpoint);\n for (const [key, endpoint] of Object.entries(REGION_API_ENDPOINTS)) {\n if (normalizeApiEndpoint(endpoint) === normalized) {\n return key;\n }\n }\n return undefined;\n}\n\nfunction normalizeApiEndpoint(apiEndpoint: string): string {\n return apiEndpoint.trim().replace(/\\/+$/, \"\").toLowerCase();\n}\n\nfunction parseSshStatus(stdout: string): \"enabled\" | \"disabled\" {\n return stdout.toLowerCase().includes(\"enabled\") && !stdout.toLowerCase().includes(\"disabled\") ? \"enabled\" : \"disabled\";\n}\n\nfunction buildPortForwardParams(\n target: InspectorTunnelTarget,\n localPort: number,\n): PortForwardParams {\n return {\n appName: resolveTunnelAppName(target),\n localPort,\n remoteHost: INSPECTOR_REMOTE_HOST,\n remotePort: INSPECTOR_REMOTE_PORT,\n keepAliveSeconds: TUNNEL_KEEPALIVE_SECONDS,\n ...(target.cfHomeDir === undefined ? {} : { cfHomeDir: target.cfHomeDir }),\n ...(target.command === undefined ? {} : { command: target.command }),\n ...(target.instanceIndex === undefined ? {} : { instanceIndex: target.instanceIndex }),\n };\n}\n\nfunction resolveTunnelAppName(target: InspectorTunnelTarget): string {\n const appName = target.appName ?? target.app;\n if (appName === undefined || appName.trim().length === 0) {\n throw new Error(\"CF app name is required for the inspector tunnel.\");\n }\n return appName;\n}\n\nasync function raceForwardReadiness(handle: PortForwardHandle, dependencies: TunnelDependencies): Promise<boolean> {\n const controller = new AbortController();\n let markFailed: () => void = () => {\n return;\n };\n const failedEarly = new Promise<false>((resolve) => {\n markFailed = (): void => {\n resolve(false);\n };\n handle.process.once(\"exit\", markFailed);\n handle.process.once(\"error\", markFailed);\n });\n const ready = dependencies.waitForLocalPort(handle.localPort, TUNNEL_READY_TIMEOUT_MS, controller.signal);\n try {\n return await Promise.race([ready, failedEarly]);\n } finally {\n controller.abort();\n handle.process.removeListener(\"exit\", markFailed);\n handle.process.removeListener(\"error\", markFailed);\n }\n}\n\nfunction resolveCommand(command?: string): { readonly bin: string; readonly argsPrefix: readonly string[] } {\n const resolvedBin = command ?? process.env[\"CF_LIVE_TRACE_CF_BIN\"] ?? \"cf\";\n return /\\.(?:c|m)?js$/i.test(resolvedBin)\n ? { bin: process.execPath, argsPrefix: [resolvedBin] }\n : { bin: resolvedBin, argsPrefix: [] };\n}\n\nfunction buildCfEnv(cfHomeDir?: string, envOverrides?: Record<string, string>): NodeJS.ProcessEnv {\n const env = { ...process.env };\n delete env[\"SAP_EMAIL\"];\n delete env[\"SAP_PASSWORD\"];\n if (cfHomeDir !== undefined && cfHomeDir.length > 0) {\n env[\"CF_HOME\"] = cfHomeDir;\n }\n return envOverrides === undefined ? env : { ...env, ...envOverrides };\n}\n\nfunction formatCfError(args: readonly string[], error: unknown, redactor?: (message: string) => string): string {\n const detail = extractErrorDetail(error);\n const message = `cf ${formatArgs(args)} failed${detail.length > 0 ? `: ${detail}` : \".\"}`;\n return redactor?.(message) ?? message;\n}\n\nfunction extractErrorDetail(error: unknown): string {\n if (!isRecord(error)) {\n return \"\";\n }\n const stderr = typeof error[\"stderr\"] === \"string\" ? error[\"stderr\"].trim() : \"\";\n if (stderr.length > 0) {\n return stderr;\n }\n const message = error[\"message\"];\n if (typeof message === \"string\") {\n return message.trim();\n }\n return message instanceof Error ? message.message.trim() : \"\";\n}\n\nfunction formatErrorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n\nfunction formatArgs(args: readonly string[]): string {\n return args.join(\" \");\n}\n\nfunction hasInspectorReadyMarker(stdout: string): boolean {\n return stdout.split(/\\r?\\n/).map((line) => line.trim()).includes(\"saptools-inspector-ready\");\n}\n\nfunction summarizeInspectorStartupOutput(stdout: string): string | undefined {\n const markers = stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"saptools-inspector-\"));\n return markers.length === 0 ? undefined : markers.join(\"; \");\n}\n\nfunction optionalDetail(detail: string | undefined): { readonly detail?: string } {\n return detail === undefined || detail.length === 0 ? {} : { detail };\n}\n\nfunction findFreePort(): Promise<number> {\n return new Promise<number>((resolve, reject) => {\n const server = createServer();\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n const port = typeof address === \"object\" && address !== null ? address.port : 0;\n server.close(() => {\n if (port === 0) {\n reject(new Error(\"Failed to allocate a local port.\"));\n return;\n }\n resolve(port);\n });\n });\n });\n}\n\nfunction waitForLocalPort(port: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n return new Promise<boolean>((resolve) => {\n let activeSocket: ReturnType<typeof netConnect> | undefined;\n let settled = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n const finish = (ready: boolean): void => {\n if (settled) {\n return;\n }\n settled = true;\n if (retryTimer !== undefined) {\n clearTimeout(retryTimer);\n }\n activeSocket?.destroy();\n activeSocket = undefined;\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(ready);\n };\n const onAbort = (): void => {\n finish(false);\n };\n const attempt = (): void => {\n if (settled) {\n return;\n }\n const socket = netConnect({ host: \"127.0.0.1\", port });\n activeSocket = socket;\n socket.once(\"connect\", () => {\n socket.destroy();\n activeSocket = undefined;\n finish(true);\n });\n socket.once(\"error\", () => {\n activeSocket = undefined;\n retryPortProbe(socket, deadline, attempt, finish, (timer) => {\n retryTimer = timer;\n });\n });\n };\n if (signal?.aborted === true) {\n finish(false);\n return;\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n attempt();\n });\n}\n\nfunction retryPortProbe(\n socket: ReturnType<typeof netConnect>,\n deadline: number,\n attempt: () => void,\n finish: (ready: boolean) => void,\n setRetryTimer: (timer: ReturnType<typeof setTimeout>) => void,\n): void {\n socket.destroy();\n if (Date.now() >= deadline) {\n finish(false);\n return;\n }\n setRetryTimer(setTimeout(attempt, TUNNEL_READY_POLL_MS));\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport interface CurrentCfTarget {\n readonly apiEndpoint: string;\n readonly regionKey?: string;\n readonly orgName: string;\n readonly spaceName: string;\n}\n\nexport interface CurrentCfTargetReadOptions {\n readonly command?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly timeoutMs?: number;\n}\n\nconst CURRENT_TARGET_TIMEOUT_MS = 30_000;\n\nexport async function readCurrentCfTarget(\n options?: CurrentCfTargetReadOptions,\n): Promise<CurrentCfTarget | undefined> {\n const opts = options ?? {};\n const command = resolveCommand(opts.command);\n const env = buildCfEnvForTarget(opts.env);\n try {\n const { stdout } = await execFileAsync(command.bin, [...command.argsPrefix, \"target\"], {\n env,\n maxBuffer: CF_MAX_BUFFER_BYTES,\n timeout: opts.timeoutMs ?? CURRENT_TARGET_TIMEOUT_MS,\n });\n return parseCurrentCfTarget(stdout);\n } catch {\n return undefined;\n }\n}\n\nexport function parseCurrentCfTarget(stdout: string): CurrentCfTarget | undefined {\n const fields = parseTargetFields(stdout);\n const apiEndpoint = fields.get(\"api endpoint\");\n const org = fields.get(\"org\");\n const space = fields.get(\"space\");\n if (!apiEndpoint || !org || !space) {\n return undefined;\n }\n const regionKey = regionKeyForApiEndpoint(apiEndpoint);\n return {\n apiEndpoint,\n ...(regionKey === undefined ? {} : { regionKey }),\n orgName: org,\n spaceName: space,\n };\n}\n\nfunction parseTargetFields(stdout: string): Map<string, string> {\n const map = new Map<string, string>();\n for (const line of stdout.split(/\\r?\\n/)) {\n const idx = line.indexOf(\":\");\n if (idx < 0) {\n continue;\n }\n const key = line.slice(0, idx).trim().toLowerCase();\n const val = line.slice(idx + 1).trim();\n if (key.length > 0 && val.length > 0) {\n map.set(key, val);\n }\n }\n return map;\n}\n\nfunction buildCfEnvForTarget(overrides?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const env = { ...process.env, ...overrides };\n delete env[\"SAP_EMAIL\"];\n delete env[\"SAP_PASSWORD\"];\n return env;\n}\n\nconst INSPECTOR_SIGNAL_COMMAND = [\n 'inspector_url=\"http://127.0.0.1:9229/json/list\"',\n 'inspector_ready() { ((command -v curl >/dev/null 2>&1 && curl -fsS --max-time 1 \"$inspector_url\" >/dev/null 2>&1) || (command -v wget >/dev/null 2>&1 && wget -qO- -T 1 \"$inspector_url\" >/dev/null 2>&1)); }',\n \"if inspector_ready; then\",\n \"echo saptools-inspector-ready\",\n \"exit 0\",\n \"fi\",\n 'node_pid=\"\"',\n \"best_score=-1\",\n \"for pid_dir in /proc/[0-9]*; do\",\n '[ -d \"$pid_dir\" ] || continue',\n 'node_exe=\"$(readlink \"$pid_dir/exe\" 2>/dev/null || true)\"',\n '[ \"${node_exe##*/}\" = \"node\" ] || continue',\n 'node_cmdline=\"$(tr \"\\\\000\" \" \" < \"$pid_dir/cmdline\" 2>/dev/null || true)\"',\n '[ -n \"$node_cmdline\" ] || continue',\n \"score=10\",\n 'if printf \"%s\\\\n\" \"$node_cmdline\" | grep -Eq \"@sap/cds|cds/bin/serve|serve\\\\.js|server\\\\.js|app\\\\.js|dist|build|index\\\\.js\"; then',\n \"score=20\",\n \"fi\",\n 'if [ \"$score\" -gt \"$best_score\" ]; then',\n 'best_score=\"$score\"',\n 'node_pid=\"${pid_dir##*/}\"',\n \"fi\",\n \"done\",\n 'if [ -z \"$node_pid\" ]; then',\n \"echo saptools-inspector-node-not-found\",\n \"exit 0\",\n \"fi\",\n 'echo \"saptools-inspector-node-pid=$node_pid\"',\n 'if kill -USR1 \"$node_pid\" 2>/dev/null; then',\n \"echo saptools-inspector-signaled\",\n \"else\",\n \"echo saptools-inspector-signal-failed\",\n \"exit 0\",\n \"fi\",\n \"attempt=0\",\n 'while [ \"$attempt\" -lt 20 ]; do',\n \"if inspector_ready; then\",\n \"echo saptools-inspector-ready\",\n \"exit 0\",\n \"fi\",\n \"attempt=$((attempt + 1))\",\n \"sleep 0.25\",\n \"done\",\n \"echo saptools-inspector-not-ready\",\n].join(\"\\\\n\");\n","import { connectInspector } from \"@saptools/cf-inspector\";\nimport type { InspectorSession } from \"@saptools/cf-inspector\";\n\nimport type { InspectorRuntimeClient } from \"./types.js\";\n\ninterface RuntimeEvaluateResult {\n readonly result?: { readonly value?: unknown };\n readonly exceptionDetails?: unknown;\n}\n\nexport async function connectRuntimeInspector(localPort: number): Promise<InspectorRuntimeClient> {\n const session = await connectInspector({ port: localPort, host: \"127.0.0.1\" });\n return new CdpRuntimeClient(session);\n}\n\nclass CdpRuntimeClient implements InspectorRuntimeClient {\n public constructor(private readonly session: InspectorSession) {}\n\n public async evaluate(expression: string, timeoutMs: number): Promise<unknown> {\n const result = await raceEvaluate(\n this.session.client.send<RuntimeEvaluateResult>(\"Runtime.evaluate\", {\n expression,\n awaitPromise: true,\n returnByValue: true,\n silent: true,\n }),\n timeoutMs,\n );\n return extractEvaluateValue(result);\n }\n\n public async close(): Promise<void> {\n await this.session.dispose();\n }\n}\n\nasync function raceEvaluate(promise: Promise<RuntimeEvaluateResult>, timeoutMs: number): Promise<RuntimeEvaluateResult> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(\"Runtime.evaluate timed out.\"));\n }, timeoutMs);\n });\n try {\n return await Promise.race([promise, timeout]);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n promise.catch(() => {\n return;\n });\n }\n}\n\nfunction extractEvaluateValue(result: RuntimeEvaluateResult): unknown {\n if (result.exceptionDetails !== undefined) {\n throw new Error(\"Runtime.evaluate failed.\");\n }\n return result.result?.value;\n}\n","export interface PreviewTruncationResult {\n readonly preview: string;\n readonly truncated: boolean;\n}\n\nexport function truncatePreview(preview: string, maxChars: number): PreviewTruncationResult {\n if (maxChars <= 0) {\n return { preview, truncated: false };\n }\n if (preview.length <= maxChars) {\n return { preview, truncated: false };\n }\n return { preview: preview.slice(0, maxChars), truncated: true };\n}\n","import { truncatePreview } from \"./preview.js\";\nimport type { DrainParseResult, LiveTraceEvent } from \"./types.js\";\n\nexport interface DrainParseOptions {\n readonly appId: string;\n readonly maxBodyBytes: number;\n}\n\nlet fallbackEventId = 0;\n\nexport function parseDrainResult(payload: unknown, options: DrainParseOptions): DrainParseResult {\n if (!isRecord(payload)) {\n return { events: [], droppedCount: 0, queueSize: 0 };\n }\n const rawEvents = Array.isArray(payload[\"events\"]) ? payload[\"events\"] : [];\n return {\n events: rawEvents\n .map((event) => parseRuntimeEvent(event, options))\n .filter((event): event is LiveTraceEvent => event !== null),\n droppedCount: readNonNegativeNumber(payload[\"droppedCount\"]),\n queueSize: readNonNegativeNumber(payload[\"queueSize\"]),\n };\n}\n\nfunction parseRuntimeEvent(payload: unknown, options: DrainParseOptions): LiveTraceEvent | null {\n if (!isRecord(payload)) {\n return null;\n }\n const rawUrl = readString(payload[\"url\"]) ?? readString(payload[\"normalizedUrl\"]) ?? readString(payload[\"path\"]);\n if (rawUrl === null) {\n return null;\n }\n const requestBody = limitBodyPreview(readString(payload[\"requestBodyPreview\"]) ?? \"\", options.maxBodyBytes);\n const responseBody = limitBodyPreview(readString(payload[\"responseBodyPreview\"]) ?? \"\", options.maxBodyBytes);\n return buildEvent(payload, rawUrl, requestBody, responseBody, options);\n}\n\nfunction buildEvent(\n payload: Record<string, unknown>,\n rawUrl: string,\n requestBody: { readonly preview: string; readonly truncated: boolean },\n responseBody: { readonly preview: string; readonly truncated: boolean },\n options: DrainParseOptions,\n): LiveTraceEvent {\n return {\n id: readString(payload[\"id\"]) ?? nextFallbackEventId(),\n timestamp: readString(payload[\"timestamp\"]) ?? new Date().toISOString(),\n appId: options.appId,\n instance: readString(payload[\"instance\"]) ?? \"0\",\n method: (readString(payload[\"method\"]) ?? \"GET\").toUpperCase(),\n path: readString(payload[\"path\"]) ?? normalizePath(rawUrl),\n url: rawUrl,\n normalizedUrl: readString(payload[\"normalizedUrl\"]) ?? normalizePath(rawUrl),\n status: readNullableNumber(payload[\"status\"]),\n durationMs: readNullableNumber(payload[\"durationMs\"]),\n requestBytes: readNonNegativeNumber(payload[\"requestBytes\"]),\n responseBytes: readNonNegativeNumber(payload[\"responseBytes\"]),\n requestHeaders: readHeaders(payload[\"requestHeaders\"]),\n responseHeaders: readHeaders(payload[\"responseHeaders\"]),\n requestBodyPreview: requestBody.preview,\n responseBodyPreview: responseBody.preview,\n requestBodyTruncated: payload[\"requestBodyTruncated\"] === true || requestBody.truncated,\n responseBodyTruncated: payload[\"responseBodyTruncated\"] === true || responseBody.truncated,\n droppedBeforeEvent: readNonNegativeNumber(payload[\"droppedBeforeEvent\"]),\n source: \"runtime-http\",\n traceId: readString(payload[\"traceId\"]) ?? readString(payload[\"id\"]) ?? \"\",\n correlationId: readString(payload[\"correlationId\"]),\n };\n}\n\nfunction readHeaders(value: unknown): Record<string, string> {\n if (!isRecord(value)) {\n return {};\n }\n const headers: Record<string, string> = {};\n for (const [key, rawValue] of Object.entries(value)) {\n const header = readHeaderValue(rawValue);\n if (header !== null) {\n headers[key] = header;\n }\n }\n return headers;\n}\n\nfunction readHeaderValue(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item)).join(\", \");\n }\n return null;\n}\n\nfunction limitBodyPreview(preview: string, maxChars: number): { readonly preview: string; readonly truncated: boolean } {\n return truncatePreview(preview, maxChars);\n}\n\nfunction normalizePath(rawUrl: string): string {\n try {\n const parsed = new URL(rawUrl, \"https://saptools.local\");\n return `${parsed.pathname}${parsed.search}`;\n } catch {\n return rawUrl;\n }\n}\n\nfunction readString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction readNullableNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction readNonNegativeNumber(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? value : 0;\n}\n\nfunction nextFallbackEventId(): string {\n fallbackEventId += 1;\n return `runtime-${String(fallbackEventId)}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","export const CF_LIVE_TRACE_GLOBAL_NAME = \"__SAPTOOLS_CF_LIVE_TRACE__\";\nexport const CF_LIVE_TRACE_RUNTIME_VERSION = 2;\n\nexport interface RuntimeInstallOptions {\n readonly appId: string;\n readonly instance: string;\n readonly captureHeaders: boolean;\n readonly captureRequestBody: boolean;\n readonly captureResponseBody: boolean;\n readonly maxBodyBytes: number;\n readonly maxEvents: number;\n}\n\nexport interface StopExpressionOptions {\n readonly uninstallRuntimeHook: boolean;\n}\n\nexport const CF_LIVE_TRACE_RUNTIME_SOURCE = `\n(() => {\n const name = '${CF_LIVE_TRACE_GLOBAL_NAME}';\n const runtimeVersion = ${String(CF_LIVE_TRACE_RUNTIME_VERSION)};\n const existing = globalThis[name];\n if (existing && typeof existing.version === 'number' && existing.version >= runtimeVersion) return existing;\n if (existing && typeof existing.uninstall === 'function') {\n try {\n existing.uninstall();\n } catch {}\n }\n let BufferCtor = globalThis.Buffer;\n const state = {\n version: runtimeVersion,\n installed: false,\n enabled: false,\n options: { appId: '', instance: '0', captureHeaders: true, captureRequestBody: true, captureResponseBody: true, maxBodyBytes: 4096, maxEvents: 1000 },\n queue: [],\n droppedCount: 0,\n originals: {},\n seen: new WeakSet(),\n nextId: 1\n };\n const loadRequire = () => {\n if (typeof require === 'function') return require;\n if (globalThis.process && globalThis.process.mainModule && typeof globalThis.process.mainModule.require === 'function') {\n return globalThis.process.mainModule.require.bind(globalThis.process.mainModule);\n }\n return null;\n };\n const loadModule = async (moduleName) => {\n const requireFn = loadRequire();\n if (requireFn) return requireFn(moduleName);\n if (globalThis.process && typeof globalThis.process.getBuiltinModule === 'function') {\n return globalThis.process.getBuiltinModule(moduleName);\n }\n return await import('node:' + moduleName);\n };\n const toHeaderRecord = (headers) => {\n const output = {};\n if (!headers || !state.options.captureHeaders) return output;\n for (const key of Object.keys(headers)) {\n const value = headers[key];\n output[key] = Array.isArray(value) ? value.join(', ') : String(value);\n }\n return output;\n };\n const chunkText = (chunk) => {\n if (chunk === undefined || chunk === null) return '';\n if (BufferCtor && BufferCtor.isBuffer(chunk)) return chunk.toString('utf8');\n if (typeof chunk === 'string') return chunk;\n if (chunk instanceof Uint8Array && BufferCtor) return BufferCtor.from(chunk).toString('utf8');\n return '';\n };\n const byteLength = (text) => BufferCtor ? BufferCtor.byteLength(text) : text.length;\n const appendPreview = (current, chunk, enabled) => {\n if (!enabled) return current;\n const text = chunkText(chunk);\n if (state.options.maxBodyBytes <= 0) return current + text;\n if (current.length >= state.options.maxBodyBytes) return current;\n return (current + text).slice(0, state.options.maxBodyBytes);\n };\n const enqueue = (event) => {\n if (state.queue.length >= state.options.maxEvents) {\n state.queue.shift();\n state.droppedCount += 1;\n }\n state.queue.push(event);\n };\n const observe = (req, res) => {\n if (!state.enabled || !req || !res || state.seen.has(req)) return;\n state.seen.add(req);\n const started = Date.now();\n const initialUrl = String(req.url || '');\n const traceId = String(state.nextId++);\n let requestBytes = 0;\n let responseBytes = 0;\n let requestPreview = '';\n let responsePreview = '';\n let finished = false;\n const originalReqEmit = req.emit;\n const originalWrite = res.write;\n const originalEnd = res.end;\n req.emit = function patchedReqEmit(eventName, ...args) {\n if (eventName === 'data' && args[0] !== undefined) {\n const text = chunkText(args[0]);\n requestBytes += byteLength(text);\n requestPreview = appendPreview(requestPreview, args[0], state.options.captureRequestBody);\n }\n return originalReqEmit.apply(this, [eventName, ...args]);\n };\n res.write = function patchedWrite(chunk, ...args) {\n const text = chunkText(chunk);\n responseBytes += byteLength(text);\n responsePreview = appendPreview(responsePreview, chunk, state.options.captureResponseBody);\n return originalWrite.apply(this, [chunk, ...args]);\n };\n res.end = function patchedEnd(chunk, ...args) {\n if (chunk !== undefined) {\n const text = chunkText(chunk);\n responseBytes += byteLength(text);\n responsePreview = appendPreview(responsePreview, chunk, state.options.captureResponseBody);\n }\n return originalEnd.apply(this, [chunk, ...args]);\n };\n const finish = () => {\n if (finished) return;\n finished = true;\n req.emit = originalReqEmit;\n res.write = originalWrite;\n res.end = originalEnd;\n const rawUrl = initialUrl || String(req.url || '');\n enqueue({\n id: traceId,\n timestamp: new Date().toISOString(),\n instance: state.options.instance,\n method: String(req.method || 'GET').toUpperCase(),\n path: rawUrl.split('?')[0] || rawUrl,\n url: rawUrl,\n normalizedUrl: rawUrl,\n status: typeof res.statusCode === 'number' ? res.statusCode : null,\n durationMs: Date.now() - started,\n requestBytes,\n responseBytes,\n requestHeaders: toHeaderRecord(req.headers),\n responseHeaders: toHeaderRecord(typeof res.getHeaders === 'function' ? res.getHeaders() : {}),\n requestBodyPreview: requestPreview,\n responseBodyPreview: responsePreview,\n requestBodyTruncated: state.options.maxBodyBytes > 0 && requestPreview.length >= state.options.maxBodyBytes,\n responseBodyTruncated: state.options.maxBodyBytes > 0 && responsePreview.length >= state.options.maxBodyBytes,\n droppedBeforeEvent: state.droppedCount,\n traceId,\n correlationId: req.headers && typeof req.headers['x-saptools-trace-id'] === 'string' ? req.headers['x-saptools-trace-id'] : null\n });\n };\n res.once('finish', finish);\n res.once('close', finish);\n };\n const patchEmit = (serverPrototype) => {\n if (!serverPrototype || serverPrototype.emit.__saptoolsCfLiveTracePatched) return undefined;\n const original = serverPrototype.emit;\n const patched = function patchedServerEmit(eventName, ...args) {\n if (eventName === 'request') observe(args[0], args[1]);\n return original.apply(this, [eventName, ...args]);\n };\n patched.__saptoolsCfLiveTracePatched = true;\n serverPrototype.emit = patched;\n return original;\n };\n const toTransportLimit = (value) => {\n const numeric = Number(value);\n return Number.isFinite(numeric) && numeric > 0 ? Math.floor(numeric) : 0;\n };\n const limitPreview = (event, previewKey, truncatedKey, maxChars) => {\n const preview = event[previewKey];\n if (maxChars <= 0 || typeof preview !== 'string' || preview.length <= maxChars) return event;\n return { ...event, [previewKey]: preview.slice(0, maxChars), [truncatedKey]: true };\n };\n const eventForDrain = (event, maxChars) => {\n if (!event || typeof event !== 'object') return event;\n let output = { ...event };\n output = limitPreview(output, 'requestBodyPreview', 'requestBodyTruncated', maxChars);\n output = limitPreview(output, 'responseBodyPreview', 'responseBodyTruncated', maxChars);\n return output;\n };\n const api = {\n version: runtimeVersion,\n async install(options) {\n state.options = { ...state.options, ...options };\n if (!state.installed) {\n if (!BufferCtor) {\n const bufferModule = await loadModule('buffer');\n BufferCtor = bufferModule && bufferModule.Buffer ? bufferModule.Buffer : BufferCtor;\n }\n const http = await loadModule('http');\n const https = await loadModule('https');\n state.originals.httpServerEmit = patchEmit(http && http.Server && http.Server.prototype);\n state.originals.httpsServerEmit = patchEmit(https && https.Server && https.Server.prototype);\n state.installed = true;\n }\n state.enabled = true;\n return api.status();\n },\n disable() {\n state.enabled = false;\n return api.status();\n },\n drainEvents(maxCount, maxTransportBodyBytes) {\n const count = Math.max(0, Math.min(Number(maxCount) || 0, state.queue.length));\n const transportLimit = toTransportLimit(maxTransportBodyBytes);\n const events = state.queue.splice(0, count).map((event) => eventForDrain(event, transportLimit));\n return { events, droppedCount: state.droppedCount, queueSize: state.queue.length };\n },\n status() {\n return { installed: state.installed, enabled: state.enabled, queueSize: state.queue.length, droppedCount: state.droppedCount, maxEvents: state.options.maxEvents };\n },\n async uninstall() {\n state.enabled = false;\n const http = await loadModule('http');\n const https = await loadModule('https');\n if (state.originals.httpServerEmit && http && http.Server) http.Server.prototype.emit = state.originals.httpServerEmit;\n if (state.originals.httpsServerEmit && https && https.Server) https.Server.prototype.emit = state.originals.httpsServerEmit;\n state.installed = false;\n return api.status();\n }\n };\n globalThis[name] = api;\n return api;\n})()\n`;\n\nexport function buildInstallExpression(options: RuntimeInstallOptions): string {\n return `${CF_LIVE_TRACE_RUNTIME_SOURCE}.install(${JSON.stringify(options)})`;\n}\n\nexport function buildDrainExpression(maxCount: number, maxTransportBodyBytes: number): string {\n return `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.drainEvents(${String(maxCount)}, ${String(maxTransportBodyBytes)}) ?? { events: [], droppedCount: 0, queueSize: 0 }`;\n}\n\nexport function buildStopExpression(options: StopExpressionOptions): string {\n return options.uninstallRuntimeHook\n ? `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.uninstall() ?? { installed: false, enabled: false }`\n : `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.disable() ?? { installed: false, enabled: false }`;\n}\n","import type { LiveTraceEvent, LiveTraceUrlSummary } from \"./types.js\";\n\ntype StatusBucket = \"2xx\" | \"3xx\" | \"4xx\" | \"5xx\" | \"unknown\";\n\ninterface MutableSummary {\n readonly normalizedUrl: string;\n readonly displayUrl: string;\n readonly methods: Set<string>;\n totalCount: number;\n readonly statusCounts: Record<StatusBucket, number>;\n latestStatus: number | null;\n latestDurationMs: number | null;\n latestSeenAt: string;\n}\n\nexport function buildUrlSummaries(events: readonly LiveTraceEvent[]): LiveTraceUrlSummary[] {\n const summaries = new Map<string, MutableSummary>();\n for (const event of events) {\n const normalizedUrl = normalizeEventUrl(event);\n const current = summaries.get(normalizedUrl) ?? createSummary(normalizedUrl);\n updateSummary(current, event);\n summaries.set(normalizedUrl, current);\n }\n return [...summaries.values()]\n .map(toImmutableSummary)\n .sort((left, right) => right.latestSeenAt.localeCompare(left.latestSeenAt));\n}\n\nexport function normalizeEventUrl(event: LiveTraceEvent): string {\n const candidate = event.normalizedUrl.length > 0 ? event.normalizedUrl : event.url.length > 0 ? event.url : event.path;\n return normalizeUrl(candidate);\n}\n\nfunction updateSummary(summary: MutableSummary, event: LiveTraceEvent): void {\n summary.methods.add(event.method);\n summary.totalCount += 1;\n summary.statusCounts[toStatusBucket(event.status)] += 1;\n if (event.timestamp >= summary.latestSeenAt) {\n summary.latestStatus = event.status;\n summary.latestDurationMs = event.durationMs;\n summary.latestSeenAt = event.timestamp;\n }\n}\n\nfunction normalizeUrl(rawUrl: string): string {\n if (rawUrl.trim().length === 0) {\n return rawUrl;\n }\n try {\n const parsed = new URL(rawUrl, \"https://saptools.local\");\n return `${parsed.pathname}${parsed.search}`;\n } catch {\n return rawUrl;\n }\n}\n\nfunction createSummary(normalizedUrl: string): MutableSummary {\n return {\n normalizedUrl,\n displayUrl: normalizedUrl,\n methods: new Set<string>(),\n totalCount: 0,\n statusCounts: { \"2xx\": 0, \"3xx\": 0, \"4xx\": 0, \"5xx\": 0, unknown: 0 },\n latestStatus: null,\n latestDurationMs: null,\n latestSeenAt: \"\",\n };\n}\n\nfunction toImmutableSummary(summary: MutableSummary): LiveTraceUrlSummary {\n return {\n normalizedUrl: summary.normalizedUrl,\n displayUrl: summary.displayUrl,\n methods: [...summary.methods].sort(),\n totalCount: summary.totalCount,\n statusCounts: { ...summary.statusCounts },\n latestStatus: summary.latestStatus,\n latestDurationMs: summary.latestDurationMs,\n latestSeenAt: summary.latestSeenAt,\n };\n}\n\nfunction toStatusBucket(status: number | null): StatusBucket {\n if (status === null) {\n return \"unknown\";\n }\n if (status >= 200 && status < 300) {\n return \"2xx\";\n }\n if (status >= 300 && status < 400) {\n return \"3xx\";\n }\n if (status >= 400 && status < 500) {\n return \"4xx\";\n }\n if (status >= 500 && status < 600) {\n return \"5xx\";\n }\n return \"unknown\";\n}\n","import { ensureSshEnabled, openInspectorTunnel, prepareCfSession, startNodeInspector } from \"./cf.js\";\nimport { connectRuntimeInspector } from \"./inspector.js\";\nimport { parseDrainResult } from \"./payload.js\";\nimport { buildDrainExpression, buildInstallExpression, buildStopExpression } from \"./runtime-source.js\";\nimport { buildUrlSummaries } from \"./summary.js\";\nimport type {\n CfLiveTraceTarget,\n InspectorStartupResult,\n InspectorRuntimeClient,\n LiveTraceEvent,\n LiveTraceStartOptions,\n LiveTraceStateEvent,\n LiveTraceStopOptions,\n TunnelOpenResult,\n} from \"./types.js\";\n\nexport interface LiveTraceSessionOptions {\n readonly target: CfLiveTraceTarget;\n readonly onState?: (event: LiveTraceStateEvent) => void;\n readonly onEvents?: (events: readonly LiveTraceEvent[]) => void;\n readonly onSummary?: (summary: ReturnType<typeof buildUrlSummaries>) => void;\n readonly onLog?: (message: string) => void;\n}\n\nexport interface LiveTraceDependencies {\n prepareCfSession(target: CfLiveTraceTarget): Promise<void>;\n ensureSshEnabled(target: CfLiveTraceTarget): Promise<void>;\n tryStartNodeInspector(target: CfLiveTraceTarget): Promise<boolean | InspectorStartupResult>;\n openInspectorTunnel(target: CfLiveTraceTarget): Promise<TunnelOpenResult>;\n connectInspector(localPort: number): Promise<InspectorRuntimeClient>;\n setInterval(callback: () => void, ms: number): NodeJS.Timeout;\n clearInterval(handle: NodeJS.Timeout): void;\n}\n\nconst DRAIN_INTERVAL_MS = 250;\nconst DRAIN_BATCH_SIZE = 50;\nconst RUNTIME_QUEUE_SIZE = 1000;\nconst CONTROL_EVALUATE_TIMEOUT_MS = 5000;\nconst DRAIN_EVALUATE_TIMEOUT_MS = 10000;\nconst DRAIN_TIMEOUT_RETRY_LIMIT = 3;\nconst DRAIN_TRANSPORT_BODY_LIMIT = 20_000;\n\nconst defaultDependencies: LiveTraceDependencies = {\n prepareCfSession,\n ensureSshEnabled,\n tryStartNodeInspector: startNodeInspector,\n openInspectorTunnel,\n connectInspector: connectRuntimeInspector,\n setInterval,\n clearInterval,\n};\n\nexport class LiveTraceSession {\n private readonly dependencies: LiveTraceDependencies;\n private readonly events: LiveTraceEvent[] = [];\n private consecutiveDrainTimeouts = 0;\n private drainInFlight = false;\n private inspectorClient: InspectorRuntimeClient | undefined;\n private pollTimer: NodeJS.Timeout | undefined;\n private state: LiveTraceStateEvent[\"state\"] = \"idle\";\n private stopRequested = false;\n private tunnelHandle: { readonly localPort: number; readonly stop: () => void } | undefined;\n\n public constructor(\n private readonly options: LiveTraceSessionOptions,\n dependencies: Partial<LiveTraceDependencies> = {},\n ) {\n this.dependencies = { ...defaultDependencies, ...dependencies };\n }\n\n public async start(options: LiveTraceStartOptions = {}): Promise<void> {\n if (this.isRunning()) {\n return;\n }\n this.stopRequested = false;\n await this.startRuntimeTrace(resolveStartOptions(options));\n }\n\n public async stop(options: LiveTraceStopOptions): Promise<void> {\n this.stopRequested = true;\n if (!this.isRunning()) {\n if (this.state === \"error\" && options.reason === \"error\") {\n return;\n }\n this.postState(\"stopped\", `Trace stopped (${options.reason}).`, false, false);\n return;\n }\n const hadRuntimeHook = this.inspectorClient !== undefined;\n this.postState(\"stopping\", `Stopping trace (${options.reason}).`, hadRuntimeHook, hadRuntimeHook);\n const uninstalled = await this.stopRuntimeTrace(options.uninstallRuntimeHook);\n this.postState(\"stopped\", `Trace stopped (${options.reason}).`, false, hadRuntimeHook && !uninstalled);\n }\n\n public isRunning(): boolean {\n return [\"preparing\", \"enabling-ssh\", \"starting-inspector\", \"opening-tunnel\", \"injecting\", \"streaming\", \"stopping\"].includes(this.state);\n }\n\n private async startRuntimeTrace(options: Required<LiveTraceStartOptions>): Promise<void> {\n try {\n this.postState(\"preparing\", \"Preparing Cloud Foundry session.\", false, false);\n await this.dependencies.prepareCfSession(this.options.target);\n if (this.shouldStop()) {\n return;\n }\n await this.startInspector(options);\n } catch (error) {\n this.log(`Live Trace startup failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false);\n const startupError = toStartupError(error);\n if (!this.shouldStop()) {\n this.postState(\"error\", startupError.stateMessage, false, false);\n }\n throw startupError;\n }\n }\n\n private async startInspector(options: Required<LiveTraceStartOptions>): Promise<void> {\n this.postState(\"enabling-ssh\", \"Ensuring CF SSH access.\", false, false);\n await this.dependencies.ensureSshEnabled(this.options.target);\n if (this.shouldStop()) {\n return;\n }\n this.postState(\"starting-inspector\", \"Requesting Node Inspector startup.\", false, false);\n this.reportInspectorStartup(await this.dependencies.tryStartNodeInspector(this.options.target));\n if (this.shouldStop()) {\n return;\n }\n this.postState(\"opening-tunnel\", \"Opening Node Inspector tunnel.\", false, false);\n const tunnel = await this.dependencies.openInspectorTunnel(this.options.target);\n await this.attachInspector(tunnel, options);\n }\n\n private async attachInspector(tunnel: TunnelOpenResult, options: Required<LiveTraceStartOptions>): Promise<void> {\n if (this.shouldStop()) {\n stopLateTunnel(tunnel);\n return;\n }\n if (tunnel.status !== \"ready\") {\n throw new LiveTraceStartupError(\n \"Node Inspector is not reachable on 127.0.0.1:9229.\",\n \"Node Inspector is not reachable on 127.0.0.1:9229.\",\n );\n }\n this.tunnelHandle = tunnel.handle;\n this.inspectorClient = await this.dependencies.connectInspector(tunnel.handle.localPort);\n this.postState(\"injecting\", \"Installing runtime HTTP trace hook.\", false, false);\n await this.installRuntimeHook(options);\n this.startPolling(options.maxBodyBytes);\n this.postState(\"streaming\", \"Streaming runtime HTTP trace events.\", true, false);\n }\n\n private async installRuntimeHook(options: Required<LiveTraceStartOptions>): Promise<void> {\n await this.requireInspector().evaluate(buildInstallExpression({\n appId: this.options.target.app,\n instance: String(this.options.target.instanceIndex ?? 0),\n captureHeaders: options.captureHeaders,\n captureRequestBody: options.captureRequestBody,\n captureResponseBody: options.captureResponseBody,\n maxBodyBytes: options.maxBodyBytes,\n maxEvents: options.runtimeQueueSize,\n }), CONTROL_EVALUATE_TIMEOUT_MS);\n }\n\n private startPolling(maxBodyBytes: number): void {\n this.stopPolling();\n this.consecutiveDrainTimeouts = 0;\n this.pollTimer = this.dependencies.setInterval(() => {\n void this.drainTraceEvents(maxBodyBytes);\n }, DRAIN_INTERVAL_MS);\n }\n\n private async drainTraceEvents(maxBodyBytes: number): Promise<void> {\n if (this.drainInFlight || this.inspectorClient === undefined || this.state !== \"streaming\") {\n return;\n }\n this.drainInFlight = true;\n try {\n const payload = await this.inspectorClient.evaluate(\n buildDrainExpression(DRAIN_BATCH_SIZE, resolveDrainTransportBodyLimit(maxBodyBytes)),\n DRAIN_EVALUATE_TIMEOUT_MS,\n );\n this.consecutiveDrainTimeouts = 0;\n this.publishDrainedEvents(payload, maxBodyBytes);\n } catch (error) {\n await this.handleDrainFailure(error);\n } finally {\n this.drainInFlight = false;\n }\n }\n\n private publishDrainedEvents(payload: unknown, maxBodyBytes: number): void {\n const drained = parseDrainResult(payload, { appId: this.options.target.app, maxBodyBytes });\n if (drained.events.length === 0) {\n return;\n }\n this.events.push(...drained.events);\n this.events.splice(0, Math.max(0, this.events.length - RUNTIME_QUEUE_SIZE));\n this.options.onEvents?.(drained.events);\n this.options.onSummary?.(buildUrlSummaries(this.events));\n }\n\n private async handleDrainFailure(error: unknown): Promise<void> {\n if (isEvaluateTimeout(error)) {\n this.consecutiveDrainTimeouts += 1;\n if (this.consecutiveDrainTimeouts < DRAIN_TIMEOUT_RETRY_LIMIT) {\n this.log(`Live Trace drain timed out for ${this.options.target.app}; retrying (${String(this.consecutiveDrainTimeouts)}/${String(DRAIN_TIMEOUT_RETRY_LIMIT)}).`);\n return;\n }\n }\n this.log(`Live Trace stream failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false);\n this.postState(\"error\", \"Runtime HTTP trace connection was lost.\", false, true);\n }\n\n private async stopRuntimeTrace(uninstallRuntimeHook: boolean): Promise<boolean> {\n this.stopPolling();\n this.consecutiveDrainTimeouts = 0;\n const uninstalled = await this.stopInspectorHook(uninstallRuntimeHook);\n await this.closeInspectorClient();\n this.stopTunnel();\n return uninstalled;\n }\n\n private async closeInspectorClient(): Promise<void> {\n const client = this.inspectorClient;\n this.inspectorClient = undefined;\n try {\n await client?.close();\n } catch (error) {\n this.log(`Live Trace inspector close failed for ${this.options.target.app}: ${formatError(error)}`);\n }\n }\n\n private stopTunnel(): void {\n const tunnel = this.tunnelHandle;\n this.tunnelHandle = undefined;\n try {\n tunnel?.stop();\n } catch (error) {\n this.log(`Live Trace tunnel cleanup failed for ${this.options.target.app}: ${formatError(error)}`);\n }\n }\n\n private async stopInspectorHook(uninstallRuntimeHook: boolean): Promise<boolean> {\n if (this.inspectorClient === undefined) {\n return true;\n }\n try {\n await this.inspectorClient.evaluate(buildStopExpression({ uninstallRuntimeHook }), CONTROL_EVALUATE_TIMEOUT_MS);\n return uninstallRuntimeHook;\n } catch (error) {\n this.log(`Live Trace cleanup failed for ${this.options.target.app}: ${formatError(error)}`);\n return false;\n }\n }\n\n private stopPolling(): void {\n if (this.pollTimer === undefined) {\n return;\n }\n this.dependencies.clearInterval(this.pollTimer);\n this.pollTimer = undefined;\n }\n\n private postState(state: LiveTraceStateEvent[\"state\"], message: string, runtimeHookInstalled: boolean, runtimeHookMayRemain: boolean): void {\n this.state = state;\n this.options.onState?.({\n state,\n app: this.options.target.app,\n instance: String(this.options.target.instanceIndex ?? 0),\n message,\n runtimeHookInstalled,\n runtimeHookMayRemain,\n });\n }\n\n private requireInspector(): InspectorRuntimeClient {\n if (this.inspectorClient === undefined) {\n throw new Error(\"Inspector client is not connected.\");\n }\n return this.inspectorClient;\n }\n\n private shouldStop(): boolean {\n return this.stopRequested;\n }\n\n private log(message: string): void {\n this.options.onLog?.(message);\n }\n\n private reportInspectorStartup(result: boolean | InspectorStartupResult): void {\n const normalized = normalizeInspectorStartupResult(result);\n if (normalized.status === \"ready\") {\n return;\n }\n const detail = normalized.detail === undefined ? \"\" : `: ${normalized.detail}`;\n this.log(`Node Inspector startup was not confirmed for ${this.options.target.app}${detail}`);\n }\n}\n\nclass LiveTraceStartupError extends Error {\n public constructor(\n message: string,\n public readonly stateMessage: string,\n cause?: unknown,\n ) {\n super(message, cause === undefined ? undefined : { cause });\n }\n}\n\nfunction resolveStartOptions(options: LiveTraceStartOptions): Required<LiveTraceStartOptions> {\n return {\n captureHeaders: options.captureHeaders ?? true,\n captureRequestBody: options.captureRequestBody ?? true,\n captureResponseBody: options.captureResponseBody ?? true,\n maxBodyBytes: options.maxBodyBytes ?? 4096,\n runtimeQueueSize: options.runtimeQueueSize ?? RUNTIME_QUEUE_SIZE,\n };\n}\n\nfunction stopLateTunnel(tunnel: TunnelOpenResult): void {\n if (tunnel.status === \"ready\") {\n tunnel.handle.stop();\n }\n}\n\nfunction resolveDrainTransportBodyLimit(maxBodyBytes: number): number {\n return maxBodyBytes > 0 ? Math.min(maxBodyBytes, DRAIN_TRANSPORT_BODY_LIMIT) : DRAIN_TRANSPORT_BODY_LIMIT;\n}\n\nfunction isEvaluateTimeout(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(\"Runtime.evaluate timed out\");\n}\n\nfunction toStartupError(error: unknown): LiveTraceStartupError {\n if (error instanceof LiveTraceStartupError) {\n return error;\n }\n return new LiveTraceStartupError(\n \"Runtime HTTP trace could not be started.\",\n \"Runtime HTTP trace could not be started.\",\n error,\n );\n}\n\nfunction normalizeInspectorStartupResult(result: boolean | InspectorStartupResult): InspectorStartupResult {\n return typeof result === \"boolean\"\n ? { status: result ? \"ready\" : \"not-ready\" }\n : result;\n}\n\nfunction formatError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n","import { readCurrentCfTarget, type CurrentCfTarget, type CurrentCfTargetReadOptions } from \"../cf.js\";\nimport type { CfLiveTraceTarget, LiveTraceStartOptions } from \"../types.js\";\n\nexport type OutputFormat = \"ndjson\" | \"summary\" | \"json\";\n\nexport interface CliFlags {\n readonly region?: string;\n readonly apiEndpoint?: string;\n readonly org?: string;\n readonly space?: string;\n readonly app?: string;\n readonly email?: string;\n readonly password?: string;\n readonly instance?: string;\n readonly cfHome?: string;\n readonly cfCommand?: string;\n readonly duration?: string;\n readonly maxEvents?: string;\n readonly maxBodyBytes?: string;\n readonly captureHeaders?: boolean;\n readonly captureRequestBody?: boolean;\n readonly captureResponseBody?: boolean;\n readonly uninstallOnExit?: boolean;\n readonly format?: string;\n readonly quiet?: boolean;\n}\n\nexport interface RunOptions {\n readonly target: CfLiveTraceTarget;\n readonly trace: Required<LiveTraceStartOptions>;\n readonly limits: {\n readonly durationMs?: number;\n readonly maxEvents?: number;\n };\n readonly format: OutputFormat;\n readonly uninstallOnExit: boolean;\n readonly quiet: boolean;\n}\n\nexport function buildRunOptions(flags: CliFlags, env: Record<string, string | undefined>): RunOptions {\n requireRegionOrApi(flags);\n const target = buildTarget(flags, env);\n return {\n target,\n trace: {\n captureHeaders: flags.captureHeaders !== false,\n captureRequestBody: flags.captureRequestBody !== false,\n captureResponseBody: flags.captureResponseBody !== false,\n maxBodyBytes: parseBodyLimit(flags.maxBodyBytes),\n runtimeQueueSize: 1000,\n },\n limits: buildLimits(flags),\n format: parseFormat(flags.format),\n uninstallOnExit: flags.uninstallOnExit !== false,\n quiet: flags.quiet === true,\n };\n}\n\nexport async function buildRunOptionsWithCurrentTarget(\n flags: CliFlags,\n env: Record<string, string | undefined>,\n): Promise<RunOptions> {\n return buildRunOptions(await resolveCurrentTargetFlags(flags, env), env);\n}\n\nexport function parsePositiveInteger(raw: string | undefined, label: string): number | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const value = Number.parseInt(raw, 10);\n if (!Number.isInteger(value) || value <= 0 || String(value) !== raw.trim()) {\n throw new Error(`Invalid ${label}: \"${raw}\" — expected a positive integer.`);\n }\n return value;\n}\n\nasync function resolveCurrentTargetFlags(\n flags: CliFlags,\n env: Record<string, string | undefined>,\n): Promise<CliFlags> {\n if (!needsCurrentTarget(flags)) {\n return flags;\n }\n\n const current = await readCurrentCfTarget(currentCfContext(flags, env)).catch((error: unknown) => {\n throw new Error(\n \"No current CF target found. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\n { cause: error },\n );\n });\n if (current === undefined) {\n throw new Error(\n \"No current CF target found. Run `cf target -o <org> -s <space>` or pass --region/--org/--space.\",\n );\n }\n\n return {\n ...flags,\n ...currentApiFields(flags, current),\n org: textOrFallback(flags.org, current.orgName),\n space: textOrFallback(flags.space, current.spaceName),\n };\n}\n\nfunction currentCfContext(flags: CliFlags, env: Record<string, string | undefined>): CurrentCfTargetReadOptions | undefined {\n const command = flags.cfCommand ?? env[\"CF_LIVE_TRACE_CF_BIN\"];\n const context: CurrentCfTargetReadOptions = {\n ...(command === undefined ? {} : { command }),\n ...(flags.cfHome === undefined ? {} : { env: { CF_HOME: flags.cfHome } }),\n };\n return context.command === undefined && context.env === undefined ? undefined : context;\n}\n\nfunction currentApiFields(\n flags: CliFlags,\n current: CurrentCfTarget,\n): Pick<CliFlags, \"apiEndpoint\" | \"region\"> {\n if (hasText(flags.region) || hasText(flags.apiEndpoint)) {\n return {};\n }\n return current.regionKey === undefined\n ? { apiEndpoint: current.apiEndpoint }\n : { region: current.regionKey };\n}\n\nfunction needsCurrentTarget(flags: CliFlags): boolean {\n return (!hasText(flags.region) && !hasText(flags.apiEndpoint)) || !hasText(flags.org) || !hasText(flags.space);\n}\n\nfunction hasText(value: string | undefined): boolean {\n return value !== undefined && value.trim().length > 0;\n}\n\nfunction textOrFallback(value: string | undefined, fallback: string): string {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? fallback : trimmed;\n}\n\nfunction buildTarget(flags: CliFlags, env: Record<string, string | undefined>): CfLiveTraceTarget {\n const apiPart = flags.apiEndpoint === undefined ? { region: requireText(flags.region, \"--region\") } : { apiEndpoint: requireText(flags.apiEndpoint, \"--api-endpoint\") };\n return {\n ...apiPart,\n org: requireText(flags.org, \"--org\"),\n space: requireText(flags.space, \"--space\"),\n app: requireText(flags.app, \"--app\"),\n email: resolveCredential(flags.email, env, \"SAP_EMAIL\"),\n password: resolveCredential(flags.password, env, \"SAP_PASSWORD\"),\n instanceIndex: parseInstanceIndex(flags.instance),\n ...(flags.cfHome === undefined ? {} : { cfHomeDir: requireText(flags.cfHome, \"--cf-home\") }),\n ...(flags.cfCommand === undefined ? {} : { command: requireText(flags.cfCommand, \"--cf-command\") }),\n };\n}\n\nfunction buildLimits(flags: CliFlags): RunOptions[\"limits\"] {\n const duration = parsePositiveInteger(flags.duration, \"--duration\");\n const maxEvents = parsePositiveInteger(flags.maxEvents, \"--max-events\");\n return {\n ...(duration === undefined ? {} : { durationMs: duration * 1000 }),\n ...(maxEvents === undefined ? {} : { maxEvents }),\n };\n}\n\nfunction requireRegionOrApi(flags: CliFlags): void {\n const hasRegion = flags.region !== undefined && flags.region.trim().length > 0;\n const hasApi = flags.apiEndpoint !== undefined && flags.apiEndpoint.trim().length > 0;\n if (!hasRegion && !hasApi) {\n throw new Error(\"Either --region or --api-endpoint is required.\");\n }\n}\n\nfunction requireText(value: string | undefined, label: string): string {\n if (value === undefined || value.trim().length === 0) {\n throw new Error(`${label} is required.`);\n }\n return value.trim();\n}\n\nfunction resolveCredential(value: string | undefined, env: Record<string, string | undefined>, envName: string): string {\n const directValue = value?.trim();\n if (directValue !== undefined && directValue.length > 0) {\n return directValue;\n }\n const envValue = env[envName]?.trim();\n if (envValue !== undefined && envValue.length > 0) {\n return envValue;\n }\n throw new Error(`Missing required environment variable: ${envName}`);\n}\n\nfunction parseInstanceIndex(value: string | undefined): number {\n const parsed = value === undefined ? undefined : parseNonNegativeInteger(value, \"--instance\");\n return parsed ?? 0;\n}\n\nfunction parseBodyLimit(value: string | undefined): number {\n if (value === undefined) {\n return 4096;\n }\n return parseNonNegativeInteger(value, \"--max-body-bytes\");\n}\n\nfunction parseNonNegativeInteger(raw: string, label: string): number {\n const value = Number.parseInt(raw, 10);\n if (!Number.isInteger(value) || value < 0 || String(value) !== raw.trim()) {\n throw new Error(`Invalid ${label}: \"${raw}\" — expected a non-negative integer.`);\n }\n return value;\n}\n\nfunction parseFormat(value: string | undefined): OutputFormat {\n if (value === undefined || value === \"ndjson\") {\n return \"ndjson\";\n }\n if (value === \"summary\" || value === \"json\") {\n return value;\n }\n throw new Error(`Invalid --format: \"${value}\" — expected ndjson, summary, or json.`);\n}\n","import process from \"node:process\";\n\nimport type { LiveTraceEvent, LiveTraceStateEvent } from \"../types.js\";\n\nexport function writeJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nexport function writeJsonLine(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value)}\\n`);\n}\n\nexport function writeProgress(event: LiveTraceStateEvent): void {\n process.stderr.write(`[cf-live-trace] ${event.state}: ${event.message}\\n`);\n}\n\nexport function writeLog(message: string): void {\n process.stderr.write(`[cf-live-trace] ${message}\\n`);\n}\n\nexport function writeSummaryLine(event: LiveTraceEvent): void {\n const status = event.status === null ? \"-\" : String(event.status);\n const duration = event.durationMs === null ? \"-\" : `${event.durationMs.toString()}ms`;\n process.stdout.write(`${event.timestamp} ${event.method} ${event.normalizedUrl} ${status} ${duration}\\n`);\n}\n"],"mappings":";;;AAAA,OAAOA,cAAa;;;ACApB,OAAOC,cAAa;AAEpB,SAAS,eAAe;;;ACFxB,SAAS,UAAU,aAAa;AAChC,SAAS,SAAS,UAAU;AAC5B,SAAS,WAAW,YAAY,oBAAoB;AACpD,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAI1B,IAAM,gBAAgB,UAAU,QAAQ;AAExC,IAAM,sBAAsB,IAAI,OAAO;AACvC,IAAM,wBAAwB;AAC9B,IAAM,0BAA0B;AAChC,IAAM,8BAA8B;AACpC,IAAM,wBAAwB;AAC9B,IAAM,wBAAwB;AAC9B,IAAM,2BAA2B,IAAI,KAAK;AAC1C,IAAM,0BAA0B;AAChC,IAAM,uBAAuB;AAuC7B,eAAsB,wBAAyC;AAC7D,SAAO,MAAM,QAAQ,KAAK,OAAO,GAAG,yBAAyB,CAAC;AAChE;AAEA,eAAsB,sBAAsB,WAAkC;AAC5E,QAAM,GAAG,WAAW,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACtD;AAEA,eAAsB,iBACpB,QACA,eAA+B,uBAChB;AACf,QAAM,cAAc,mBAAmB,MAAM;AAC7C,QAAM,WAAW,qBAAqB,CAAC,OAAO,OAAO,OAAO,QAAQ,CAAC;AACrE,QAAM,cAAc,gBAAgB,QAAQ,QAAQ;AACpD,QAAM,aAAa,MAAM,CAAC,OAAO,WAAW,GAAG,WAAW;AAC1D,QAAM,aAAa,MAAM,CAAC,MAAM,GAAG;AAAA,IACjC,GAAG;AAAA,IACH,cAAc,EAAE,aAAa,OAAO,OAAO,aAAa,OAAO,SAAS;AAAA,EAC1E,CAAC;AACD,QAAM,aAAa,MAAM,CAAC,UAAU,MAAM,OAAO,KAAK,MAAM,OAAO,KAAK,GAAG,WAAW;AACxF;AAEA,eAAsB,iBACpB,QACA,eAA+B,uBAChB;AACf,QAAM,WAAW,qBAAqB,CAAC,OAAO,OAAO,OAAO,QAAQ,CAAC;AACrE,QAAM,UAAU,gBAAgB,QAAQ,QAAQ;AAChD,QAAM,SAAS,MAAM,aAAa,MAAM,CAAC,eAAe,OAAO,GAAG,GAAG,OAAO;AAC5E,MAAI,eAAe,MAAM,MAAM,WAAW;AACxC;AAAA,EACF;AACA,QAAM,aAAa,MAAM,CAAC,cAAc,OAAO,GAAG,GAAG,OAAO;AAC5D,QAAM,aAAa,MAAM,CAAC,WAAW,OAAO,GAAG,GAAG,OAAO;AACzD,QAAM,aAAa,MAAM,eAAe,OAAO,KAAK,OAAO,eAAe,CAAC,MAAM,MAAM,CAAC,GAAG;AAAA,IACzF,GAAG;AAAA,IACH,WAAW;AAAA,EACb,CAAC;AACH;AAUA,eAAsB,mBACpB,QACA,eAA+B,uBACE;AACjC,QAAM,WAAW,qBAAqB,CAAC,OAAO,OAAO,OAAO,QAAQ,CAAC;AACrE,MAAI;AACF,UAAM,SAAS,MAAM,aAAa;AAAA,MAChC,eAAe,OAAO,KAAK,OAAO,eAAe,CAAC,MAAM,4BAA4B,CAAC,CAAC;AAAA,MACtF,EAAE,GAAG,gBAAgB,QAAQ,QAAQ,GAAG,WAAW,4BAA4B;AAAA,IACjF;AACA,WAAO,wBAAwB,MAAM,IACjC,EAAE,QAAQ,QAAQ,IAClB,EAAE,QAAQ,aAAa,GAAG,eAAe,gCAAgC,MAAM,CAAC,EAAE;AAAA,EACxF,SAAS,OAAO;AACd,WAAO,EAAE,QAAQ,aAAa,GAAG,eAAe,SAAS,mBAAmB,KAAK,CAAC,CAAC,EAAE;AAAA,EACvF;AACF;AAEA,eAAsB,oBACpB,QACA,eAAmC,2BACR;AAC3B,QAAM,YAAY,MAAM,aAAa,aAAa;AAClD,QAAM,SAAS,aAAa,iBAAiB,uBAAuB,QAAQ,SAAS,CAAC;AACtF,QAAM,QAAQ,MAAM,qBAAqB,QAAQ,YAAY;AAC7D,MAAI,CAAC,OAAO;AACV,WAAO,KAAK;AACZ,WAAO,EAAE,QAAQ,gBAAgB;AAAA,EACnC;AACA,SAAO,EAAE,QAAQ,SAAS,OAAO;AACnC;AAEO,SAAS,eAAe,SAAiB,eAAmC,MAAmC;AACpH,QAAM,OAAO,CAAC,OAAO,OAAO;AAC5B,MAAI,kBAAkB,QAAW;AAC/B,SAAK,KAAK,MAAM,OAAO,aAAa,CAAC;AAAA,EACvC;AACA,SAAO,CAAC,GAAG,MAAM,GAAG,IAAI;AAC1B;AAEO,SAAS,8BAAsC;AACpD,SAAO;AACT;AAEO,SAAS,qBAAqB,SAAyD;AAC5F,QAAM,SAAS,QAAQ,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,OAAO,SAAS,CAAC;AAC1F,SAAO,CAAC,YAA4B,OAAO,OAAO,CAAC,SAAS,WAAW,QAAQ,MAAM,MAAM,EAAE,KAAK,YAAY,GAAG,OAAO;AAC1H;AAEA,eAAsB,aAAa,MAAyB,SAAwC;AAClG,QAAM,UAAU,eAAe,QAAQ,OAAO;AAC9C,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,QAAQ,KAAK,CAAC,GAAG,QAAQ,YAAY,GAAG,IAAI,GAAG;AAAA,MACpF,KAAK,WAAW,QAAQ,WAAW,QAAQ,YAAY;AAAA,MACvD,WAAW;AAAA,MACX,SAAS,QAAQ,aAAa;AAAA,IAChC,CAAC;AACD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,cAAc,MAAM,OAAO,QAAQ,QAAQ,GAAG,EAAE,OAAO,MAAM,CAAC;AAAA,EAChF;AACF;AAEO,SAAS,iBAAiB,QAA8C;AAC7E,QAAM,UAAU,eAAe,OAAO,OAAO;AAC7C,QAAM,cAAc,GAAG,OAAO,OAAO,SAAS,CAAC,IAAI,OAAO,UAAU,IAAI,OAAO,OAAO,UAAU,CAAC;AACjG,QAAM,UAAU,eAAe,OAAO,SAAS,OAAO,eAAe,CAAC,MAAM,aAAa,MAAM,SAAS,OAAO,OAAO,gBAAgB,CAAC,EAAE,CAAC;AAC1I,QAAM,QAAQ,MAAM,QAAQ,KAAK,CAAC,GAAG,QAAQ,YAAY,GAAG,OAAO,GAAG;AAAA,IACpE,KAAK,WAAW,OAAO,SAAS;AAAA,IAChC,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,EAClC,CAAC;AACD,QAAM,OAAO,OAAO;AACpB,QAAM,OAAO,OAAO;AACpB,SAAO;AAAA,IACL,SAAS;AAAA,IACT,WAAW,OAAO;AAAA,IAClB,OAAa;AACX,UAAI,CAAC,MAAM,QAAQ;AACjB,cAAM,KAAK;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,wBAAwC;AAAA,EACnD,OAAO;AACT;AAEO,IAAM,4BAAgD;AAAA,EAC3D,cAAc;AAAA,EACd;AAAA,EACA;AACF;AAEA,SAAS,gBAAgB,QAA0D,UAAqD;AACtI,SAAO;AAAA,IACL,GAAI,OAAO,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,OAAO,UAAU;AAAA,IACxE,GAAI,OAAO,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,OAAO,QAAQ;AAAA,IAClE;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,QAAmE;AAC7F,MAAI,OAAO,gBAAgB,UAAa,OAAO,YAAY,KAAK,EAAE,SAAS,GAAG;AAC5E,WAAO,OAAO,YAAY,KAAK;AAAA,EACjC;AACA,MAAI,OAAO,WAAW,QAAW;AAC/B,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AACA,QAAM,WAAW,qBAAqB,OAAO,MAAM;AACnD,MAAI,aAAa,QAAW;AAC1B,UAAM,IAAI,MAAM,sBAAsB,OAAO,MAAM,EAAE;AAAA,EACvD;AACA,SAAO;AACT;AAEA,IAAM,uBAAyD;AAAA,EAC7D,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,SAAS,wBAAwB,aAAyC;AACxE,QAAM,aAAa,qBAAqB,WAAW;AACnD,aAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,oBAAoB,GAAG;AAClE,QAAI,qBAAqB,QAAQ,MAAM,YAAY;AACjD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,aAA6B;AACzD,SAAO,YAAY,KAAK,EAAE,QAAQ,QAAQ,EAAE,EAAE,YAAY;AAC5D;AAEA,SAAS,eAAe,QAAwC;AAC9D,SAAO,OAAO,YAAY,EAAE,SAAS,SAAS,KAAK,CAAC,OAAO,YAAY,EAAE,SAAS,UAAU,IAAI,YAAY;AAC9G;AAEA,SAAS,uBACP,QACA,WACmB;AACnB,SAAO;AAAA,IACL,SAAS,qBAAqB,MAAM;AAAA,IACpC;AAAA,IACA,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,GAAI,OAAO,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,OAAO,UAAU;AAAA,IACxE,GAAI,OAAO,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,OAAO,QAAQ;AAAA,IAClE,GAAI,OAAO,kBAAkB,SAAY,CAAC,IAAI,EAAE,eAAe,OAAO,cAAc;AAAA,EACtF;AACF;AAEA,SAAS,qBAAqB,QAAuC;AACnE,QAAM,UAAU,OAAO,WAAW,OAAO;AACzC,MAAI,YAAY,UAAa,QAAQ,KAAK,EAAE,WAAW,GAAG;AACxD,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AACA,SAAO;AACT;AAEA,eAAe,qBAAqB,QAA2B,cAAoD;AACjH,QAAM,aAAa,IAAI,gBAAgB;AACvC,MAAI,aAAyB,MAAM;AACjC;AAAA,EACF;AACA,QAAM,cAAc,IAAI,QAAe,CAAC,YAAY;AAClD,iBAAa,MAAY;AACvB,cAAQ,KAAK;AAAA,IACf;AACA,WAAO,QAAQ,KAAK,QAAQ,UAAU;AACtC,WAAO,QAAQ,KAAK,SAAS,UAAU;AAAA,EACzC,CAAC;AACD,QAAM,QAAQ,aAAa,iBAAiB,OAAO,WAAW,yBAAyB,WAAW,MAAM;AACxG,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK,CAAC,OAAO,WAAW,CAAC;AAAA,EAChD,UAAE;AACA,eAAW,MAAM;AACjB,WAAO,QAAQ,eAAe,QAAQ,UAAU;AAChD,WAAO,QAAQ,eAAe,SAAS,UAAU;AAAA,EACnD;AACF;AAEA,SAAS,eAAe,SAAoF;AAC1G,QAAM,cAAc,WAAW,QAAQ,IAAI,sBAAsB,KAAK;AACtE,SAAO,iBAAiB,KAAK,WAAW,IACpC,EAAE,KAAK,QAAQ,UAAU,YAAY,CAAC,WAAW,EAAE,IACnD,EAAE,KAAK,aAAa,YAAY,CAAC,EAAE;AACzC;AAEA,SAAS,WAAW,WAAoB,cAA0D;AAChG,QAAM,MAAM,EAAE,GAAG,QAAQ,IAAI;AAC7B,SAAO,IAAI,WAAW;AACtB,SAAO,IAAI,cAAc;AACzB,MAAI,cAAc,UAAa,UAAU,SAAS,GAAG;AACnD,QAAI,SAAS,IAAI;AAAA,EACnB;AACA,SAAO,iBAAiB,SAAY,MAAM,EAAE,GAAG,KAAK,GAAG,aAAa;AACtE;AAEA,SAAS,cAAc,MAAyB,OAAgB,UAAgD;AAC9G,QAAM,SAAS,mBAAmB,KAAK;AACvC,QAAM,UAAU,MAAM,WAAW,IAAI,CAAC,UAAU,OAAO,SAAS,IAAI,KAAK,MAAM,KAAK,GAAG;AACvF,SAAO,WAAW,OAAO,KAAK;AAChC;AAEA,SAAS,mBAAmB,OAAwB;AAClD,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,MAAM,QAAQ,MAAM,WAAW,MAAM,QAAQ,EAAE,KAAK,IAAI;AAC9E,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,SAAS;AAC/B,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO,QAAQ,KAAK;AAAA,EACtB;AACA,SAAO,mBAAmB,QAAQ,QAAQ,QAAQ,KAAK,IAAI;AAC7D;AAEA,SAAS,mBAAmB,OAAwB;AAClD,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,SAAO,QAAQ,KAAK,EAAE,SAAS,IAAI,QAAQ,KAAK,IAAI;AACtD;AAEA,SAAS,WAAW,MAAiC;AACnD,SAAO,KAAK,KAAK,GAAG;AACtB;AAEA,SAAS,wBAAwB,QAAyB;AACxD,SAAO,OAAO,MAAM,OAAO,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EAAE,SAAS,0BAA0B;AAC7F;AAEA,SAAS,gCAAgC,QAAoC;AAC3E,QAAM,UAAU,OACb,MAAM,OAAO,EACb,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,CAAC,SAAS,KAAK,WAAW,qBAAqB,CAAC;AAC1D,SAAO,QAAQ,WAAW,IAAI,SAAY,QAAQ,KAAK,IAAI;AAC7D;AAEA,SAAS,eAAe,QAA0D;AAChF,SAAO,WAAW,UAAa,OAAO,WAAW,IAAI,CAAC,IAAI,EAAE,OAAO;AACrE;AAEA,SAAS,eAAgC;AACvC,SAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9C,UAAM,SAAS,aAAa;AAC5B,WAAO,KAAK,SAAS,MAAM;AAC3B,WAAO,OAAO,GAAG,aAAa,MAAM;AAClC,YAAM,UAAU,OAAO,QAAQ;AAC/B,YAAM,OAAO,OAAO,YAAY,YAAY,YAAY,OAAO,QAAQ,OAAO;AAC9E,aAAO,MAAM,MAAM;AACjB,YAAI,SAAS,GAAG;AACd,iBAAO,IAAI,MAAM,kCAAkC,CAAC;AACpD;AAAA,QACF;AACA,gBAAQ,IAAI;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,iBAAiB,MAAc,WAAmB,QAAwC;AACjG,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,IAAI,QAAiB,CAAC,YAAY;AACvC,QAAI;AACJ,QAAI,UAAU;AACd,QAAI;AACJ,UAAM,SAAS,CAAC,UAAyB;AACvC,UAAI,SAAS;AACX;AAAA,MACF;AACA,gBAAU;AACV,UAAI,eAAe,QAAW;AAC5B,qBAAa,UAAU;AAAA,MACzB;AACA,oBAAc,QAAQ;AACtB,qBAAe;AACf,cAAQ,oBAAoB,SAAS,OAAO;AAC5C,cAAQ,KAAK;AAAA,IACf;AACA,UAAM,UAAU,MAAY;AAC1B,aAAO,KAAK;AAAA,IACd;AACA,UAAM,UAAU,MAAY;AAC1B,UAAI,SAAS;AACX;AAAA,MACF;AACA,YAAM,SAAS,WAAW,EAAE,MAAM,aAAa,KAAK,CAAC;AACrD,qBAAe;AACf,aAAO,KAAK,WAAW,MAAM;AAC3B,eAAO,QAAQ;AACf,uBAAe;AACf,eAAO,IAAI;AAAA,MACb,CAAC;AACD,aAAO,KAAK,SAAS,MAAM;AACzB,uBAAe;AACf,uBAAe,QAAQ,UAAU,SAAS,QAAQ,CAAC,UAAU;AAC3D,uBAAa;AAAA,QACf,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AACA,QAAI,QAAQ,YAAY,MAAM;AAC5B,aAAO,KAAK;AACZ;AAAA,IACF;AACA,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACzD,YAAQ;AAAA,EACV,CAAC;AACH;AAEA,SAAS,eACP,QACA,UACA,SACA,QACA,eACM;AACN,SAAO,QAAQ;AACf,MAAI,KAAK,IAAI,KAAK,UAAU;AAC1B,WAAO,KAAK;AACZ;AAAA,EACF;AACA,gBAAc,WAAW,SAAS,oBAAoB,CAAC;AACzD;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAeA,IAAM,4BAA4B;AAElC,eAAsB,oBACpB,SACsC;AACtC,QAAM,OAAO,WAAW,CAAC;AACzB,QAAM,UAAU,eAAe,KAAK,OAAO;AAC3C,QAAM,MAAM,oBAAoB,KAAK,GAAG;AACxC,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,QAAQ,KAAK,CAAC,GAAG,QAAQ,YAAY,QAAQ,GAAG;AAAA,MACrF;AAAA,MACA,WAAW;AAAA,MACX,SAAS,KAAK,aAAa;AAAA,IAC7B,CAAC;AACD,WAAO,qBAAqB,MAAM;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,qBAAqB,QAA6C;AAChF,QAAM,SAAS,kBAAkB,MAAM;AACvC,QAAM,cAAc,OAAO,IAAI,cAAc;AAC7C,QAAM,MAAM,OAAO,IAAI,KAAK;AAC5B,QAAM,QAAQ,OAAO,IAAI,OAAO;AAChC,MAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO;AAClC,WAAO;AAAA,EACT;AACA,QAAM,YAAY,wBAAwB,WAAW;AACrD,SAAO;AAAA,IACL;AAAA,IACA,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,UAAU;AAAA,IAC/C,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AACF;AAEA,SAAS,kBAAkB,QAAqC;AAC9D,QAAM,MAAM,oBAAI,IAAoB;AACpC,aAAW,QAAQ,OAAO,MAAM,OAAO,GAAG;AACxC,UAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,QAAI,MAAM,GAAG;AACX;AAAA,IACF;AACA,UAAM,MAAM,KAAK,MAAM,GAAG,GAAG,EAAE,KAAK,EAAE,YAAY;AAClD,UAAM,MAAM,KAAK,MAAM,MAAM,CAAC,EAAE,KAAK;AACrC,QAAI,IAAI,SAAS,KAAK,IAAI,SAAS,GAAG;AACpC,UAAI,IAAI,KAAK,GAAG;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,WAAkD;AAC7E,QAAM,MAAM,EAAE,GAAG,QAAQ,KAAK,GAAG,UAAU;AAC3C,SAAO,IAAI,WAAW;AACtB,SAAO,IAAI,cAAc;AACzB,SAAO;AACT;AAEA,IAAM,2BAA2B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,KAAK;;;AC7kBZ,SAAS,wBAAwB;AAUjC,eAAsB,wBAAwB,WAAoD;AAChG,QAAM,UAAU,MAAM,iBAAiB,EAAE,MAAM,WAAW,MAAM,YAAY,CAAC;AAC7E,SAAO,IAAI,iBAAiB,OAAO;AACrC;AAEA,IAAM,mBAAN,MAAyD;AAAA,EAChD,YAA6B,SAA2B;AAA3B;AAAA,EAA4B;AAAA,EAA5B;AAAA,EAEpC,MAAa,SAAS,YAAoB,WAAqC;AAC7E,UAAM,SAAS,MAAM;AAAA,MACnB,KAAK,QAAQ,OAAO,KAA4B,oBAAoB;AAAA,QAClE;AAAA,QACA,cAAc;AAAA,QACd,eAAe;AAAA,QACf,QAAQ;AAAA,MACV,CAAC;AAAA,MACD;AAAA,IACF;AACA,WAAO,qBAAqB,MAAM;AAAA,EACpC;AAAA,EAEA,MAAa,QAAuB;AAClC,UAAM,KAAK,QAAQ,QAAQ;AAAA,EAC7B;AACF;AAEA,eAAe,aAAa,SAAyC,WAAmD;AACtH,MAAI;AACJ,QAAM,UAAU,IAAI,QAAe,CAAC,GAAG,WAAW;AAChD,YAAQ,WAAW,MAAM;AACvB,aAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA,IACjD,GAAG,SAAS;AAAA,EACd,CAAC;AACD,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC;AAAA,EAC9C,UAAE;AACA,QAAI,UAAU,QAAW;AACvB,mBAAa,KAAK;AAAA,IACpB;AACA,YAAQ,MAAM,MAAM;AAClB;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,qBAAqB,QAAwC;AACpE,MAAI,OAAO,qBAAqB,QAAW;AACzC,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AACA,SAAO,OAAO,QAAQ;AACxB;;;ACvDO,SAAS,gBAAgB,SAAiB,UAA2C;AAC1F,MAAI,YAAY,GAAG;AACjB,WAAO,EAAE,SAAS,WAAW,MAAM;AAAA,EACrC;AACA,MAAI,QAAQ,UAAU,UAAU;AAC9B,WAAO,EAAE,SAAS,WAAW,MAAM;AAAA,EACrC;AACA,SAAO,EAAE,SAAS,QAAQ,MAAM,GAAG,QAAQ,GAAG,WAAW,KAAK;AAChE;;;ACLA,IAAI,kBAAkB;AAEf,SAAS,iBAAiB,SAAkB,SAA8C;AAC/F,MAAI,CAACC,UAAS,OAAO,GAAG;AACtB,WAAO,EAAE,QAAQ,CAAC,GAAG,cAAc,GAAG,WAAW,EAAE;AAAA,EACrD;AACA,QAAM,YAAY,MAAM,QAAQ,QAAQ,QAAQ,CAAC,IAAI,QAAQ,QAAQ,IAAI,CAAC;AAC1E,SAAO;AAAA,IACL,QAAQ,UACL,IAAI,CAAC,UAAU,kBAAkB,OAAO,OAAO,CAAC,EAChD,OAAO,CAAC,UAAmC,UAAU,IAAI;AAAA,IAC5D,cAAc,sBAAsB,QAAQ,cAAc,CAAC;AAAA,IAC3D,WAAW,sBAAsB,QAAQ,WAAW,CAAC;AAAA,EACvD;AACF;AAEA,SAAS,kBAAkB,SAAkB,SAAmD;AAC9F,MAAI,CAACA,UAAS,OAAO,GAAG;AACtB,WAAO;AAAA,EACT;AACA,QAAM,SAAS,WAAW,QAAQ,KAAK,CAAC,KAAK,WAAW,QAAQ,eAAe,CAAC,KAAK,WAAW,QAAQ,MAAM,CAAC;AAC/G,MAAI,WAAW,MAAM;AACnB,WAAO;AAAA,EACT;AACA,QAAM,cAAc,iBAAiB,WAAW,QAAQ,oBAAoB,CAAC,KAAK,IAAI,QAAQ,YAAY;AAC1G,QAAM,eAAe,iBAAiB,WAAW,QAAQ,qBAAqB,CAAC,KAAK,IAAI,QAAQ,YAAY;AAC5G,SAAO,WAAW,SAAS,QAAQ,aAAa,cAAc,OAAO;AACvE;AAEA,SAAS,WACP,SACA,QACA,aACA,cACA,SACgB;AAChB,SAAO;AAAA,IACL,IAAI,WAAW,QAAQ,IAAI,CAAC,KAAK,oBAAoB;AAAA,IACrD,WAAW,WAAW,QAAQ,WAAW,CAAC,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,IACtE,OAAO,QAAQ;AAAA,IACf,UAAU,WAAW,QAAQ,UAAU,CAAC,KAAK;AAAA,IAC7C,SAAS,WAAW,QAAQ,QAAQ,CAAC,KAAK,OAAO,YAAY;AAAA,IAC7D,MAAM,WAAW,QAAQ,MAAM,CAAC,KAAK,cAAc,MAAM;AAAA,IACzD,KAAK;AAAA,IACL,eAAe,WAAW,QAAQ,eAAe,CAAC,KAAK,cAAc,MAAM;AAAA,IAC3E,QAAQ,mBAAmB,QAAQ,QAAQ,CAAC;AAAA,IAC5C,YAAY,mBAAmB,QAAQ,YAAY,CAAC;AAAA,IACpD,cAAc,sBAAsB,QAAQ,cAAc,CAAC;AAAA,IAC3D,eAAe,sBAAsB,QAAQ,eAAe,CAAC;AAAA,IAC7D,gBAAgB,YAAY,QAAQ,gBAAgB,CAAC;AAAA,IACrD,iBAAiB,YAAY,QAAQ,iBAAiB,CAAC;AAAA,IACvD,oBAAoB,YAAY;AAAA,IAChC,qBAAqB,aAAa;AAAA,IAClC,sBAAsB,QAAQ,sBAAsB,MAAM,QAAQ,YAAY;AAAA,IAC9E,uBAAuB,QAAQ,uBAAuB,MAAM,QAAQ,aAAa;AAAA,IACjF,oBAAoB,sBAAsB,QAAQ,oBAAoB,CAAC;AAAA,IACvE,QAAQ;AAAA,IACR,SAAS,WAAW,QAAQ,SAAS,CAAC,KAAK,WAAW,QAAQ,IAAI,CAAC,KAAK;AAAA,IACxE,eAAe,WAAW,QAAQ,eAAe,CAAC;AAAA,EACpD;AACF;AAEA,SAAS,YAAY,OAAwC;AAC3D,MAAI,CAACA,UAAS,KAAK,GAAG;AACpB,WAAO,CAAC;AAAA,EACV;AACA,QAAM,UAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,KAAK,GAAG;AACnD,UAAM,SAAS,gBAAgB,QAAQ;AACvC,QAAI,WAAW,MAAM;AACnB,cAAQ,GAAG,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAA+B;AACtD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW;AAC3D,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,OAAO,IAAI,CAAC,EAAE,KAAK,IAAI;AAAA,EACpD;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,SAAiB,UAA6E;AACtH,SAAO,gBAAgB,SAAS,QAAQ;AAC1C;AAEA,SAAS,cAAc,QAAwB;AAC7C,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,QAAQ,wBAAwB;AACvD,WAAO,GAAG,OAAO,QAAQ,GAAG,OAAO,MAAM;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,OAA+B;AACjD,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,SAAS,mBAAmB,OAA+B;AACzD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAEA,SAAS,sBAAsB,OAAwB;AACrD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS,IAAI,QAAQ;AACrF;AAEA,SAAS,sBAA8B;AACrC,qBAAmB;AACnB,SAAO,WAAW,OAAO,eAAe,CAAC;AAC3C;AAEA,SAASA,UAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;;;ACjIO,IAAM,4BAA4B;AAClC,IAAM,gCAAgC;AAgBtC,IAAM,+BAA+B;AAAA;AAAA,kBAE1B,yBAAyB;AAAA,2BAChB,OAAO,6BAA6B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgNzD,SAAS,uBAAuB,SAAwC;AAC7E,SAAO,GAAG,4BAA4B,YAAY,KAAK,UAAU,OAAO,CAAC;AAC3E;AAEO,SAAS,qBAAqB,UAAkB,uBAAuC;AAC5F,SAAO,cAAc,yBAAyB,iBAAiB,OAAO,QAAQ,CAAC,KAAK,OAAO,qBAAqB,CAAC;AACnH;AAEO,SAAS,oBAAoB,SAAwC;AAC1E,SAAO,QAAQ,uBACX,cAAc,yBAAyB,0DACvC,cAAc,yBAAyB;AAC7C;;;ACjOO,SAAS,kBAAkB,QAA0D;AAC1F,QAAM,YAAY,oBAAI,IAA4B;AAClD,aAAW,SAAS,QAAQ;AAC1B,UAAM,gBAAgB,kBAAkB,KAAK;AAC7C,UAAM,UAAU,UAAU,IAAI,aAAa,KAAK,cAAc,aAAa;AAC3E,kBAAc,SAAS,KAAK;AAC5B,cAAU,IAAI,eAAe,OAAO;AAAA,EACtC;AACA,SAAO,CAAC,GAAG,UAAU,OAAO,CAAC,EAC1B,IAAI,kBAAkB,EACtB,KAAK,CAAC,MAAM,UAAU,MAAM,aAAa,cAAc,KAAK,YAAY,CAAC;AAC9E;AAEO,SAAS,kBAAkB,OAA+B;AAC/D,QAAM,YAAY,MAAM,cAAc,SAAS,IAAI,MAAM,gBAAgB,MAAM,IAAI,SAAS,IAAI,MAAM,MAAM,MAAM;AAClH,SAAO,aAAa,SAAS;AAC/B;AAEA,SAAS,cAAc,SAAyB,OAA6B;AAC3E,UAAQ,QAAQ,IAAI,MAAM,MAAM;AAChC,UAAQ,cAAc;AACtB,UAAQ,aAAa,eAAe,MAAM,MAAM,CAAC,KAAK;AACtD,MAAI,MAAM,aAAa,QAAQ,cAAc;AAC3C,YAAQ,eAAe,MAAM;AAC7B,YAAQ,mBAAmB,MAAM;AACjC,YAAQ,eAAe,MAAM;AAAA,EAC/B;AACF;AAEA,SAAS,aAAa,QAAwB;AAC5C,MAAI,OAAO,KAAK,EAAE,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,QAAQ,wBAAwB;AACvD,WAAO,GAAG,OAAO,QAAQ,GAAG,OAAO,MAAM;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,eAAuC;AAC5D,SAAO;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,SAAS,oBAAI,IAAY;AAAA,IACzB,YAAY;AAAA,IACZ,cAAc,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,EAAE;AAAA,IACnE,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AACF;AAEA,SAAS,mBAAmB,SAA8C;AACxE,SAAO;AAAA,IACL,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ;AAAA,IACpB,SAAS,CAAC,GAAG,QAAQ,OAAO,EAAE,KAAK;AAAA,IACnC,YAAY,QAAQ;AAAA,IACpB,cAAc,EAAE,GAAG,QAAQ,aAAa;AAAA,IACxC,cAAc,QAAQ;AAAA,IACtB,kBAAkB,QAAQ;AAAA,IAC1B,cAAc,QAAQ;AAAA,EACxB;AACF;AAEA,SAAS,eAAe,QAAqC;AAC3D,MAAI,WAAW,MAAM;AACnB,WAAO;AAAA,EACT;AACA,MAAI,UAAU,OAAO,SAAS,KAAK;AACjC,WAAO;AAAA,EACT;AACA,MAAI,UAAU,OAAO,SAAS,KAAK;AACjC,WAAO;AAAA,EACT;AACA,MAAI,UAAU,OAAO,SAAS,KAAK;AACjC,WAAO;AAAA,EACT;AACA,MAAI,UAAU,OAAO,SAAS,KAAK;AACjC,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ACjEA,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,8BAA8B;AACpC,IAAM,4BAA4B;AAClC,IAAM,4BAA4B;AAClC,IAAM,6BAA6B;AAEnC,IAAM,sBAA6C;AAAA,EACjD;AAAA,EACA;AAAA,EACA,uBAAuB;AAAA,EACvB;AAAA,EACA,kBAAkB;AAAA,EAClB;AAAA,EACA;AACF;AAEO,IAAM,mBAAN,MAAuB;AAAA,EAWrB,YACY,SACjB,eAA+C,CAAC,GAChD;AAFiB;AAGjB,SAAK,eAAe,EAAE,GAAG,qBAAqB,GAAG,aAAa;AAAA,EAChE;AAAA,EAJmB;AAAA,EAXF;AAAA,EACA,SAA2B,CAAC;AAAA,EACrC,2BAA2B;AAAA,EAC3B,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA,QAAsC;AAAA,EACtC,gBAAgB;AAAA,EAChB;AAAA,EASR,MAAa,MAAM,UAAiC,CAAC,GAAkB;AACrE,QAAI,KAAK,UAAU,GAAG;AACpB;AAAA,IACF;AACA,SAAK,gBAAgB;AACrB,UAAM,KAAK,kBAAkB,oBAAoB,OAAO,CAAC;AAAA,EAC3D;AAAA,EAEA,MAAa,KAAK,SAA8C;AAC9D,SAAK,gBAAgB;AACrB,QAAI,CAAC,KAAK,UAAU,GAAG;AACrB,UAAI,KAAK,UAAU,WAAW,QAAQ,WAAW,SAAS;AACxD;AAAA,MACF;AACA,WAAK,UAAU,WAAW,kBAAkB,QAAQ,MAAM,MAAM,OAAO,KAAK;AAC5E;AAAA,IACF;AACA,UAAM,iBAAiB,KAAK,oBAAoB;AAChD,SAAK,UAAU,YAAY,mBAAmB,QAAQ,MAAM,MAAM,gBAAgB,cAAc;AAChG,UAAM,cAAc,MAAM,KAAK,iBAAiB,QAAQ,oBAAoB;AAC5E,SAAK,UAAU,WAAW,kBAAkB,QAAQ,MAAM,MAAM,OAAO,kBAAkB,CAAC,WAAW;AAAA,EACvG;AAAA,EAEO,YAAqB;AAC1B,WAAO,CAAC,aAAa,gBAAgB,sBAAsB,kBAAkB,aAAa,aAAa,UAAU,EAAE,SAAS,KAAK,KAAK;AAAA,EACxI;AAAA,EAEA,MAAc,kBAAkB,SAAyD;AACvF,QAAI;AACF,WAAK,UAAU,aAAa,oCAAoC,OAAO,KAAK;AAC5E,YAAM,KAAK,aAAa,iBAAiB,KAAK,QAAQ,MAAM;AAC5D,UAAI,KAAK,WAAW,GAAG;AACrB;AAAA,MACF;AACA,YAAM,KAAK,eAAe,OAAO;AAAA,IACnC,SAAS,OAAO;AACd,WAAK,IAAI,iCAAiC,KAAK,QAAQ,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,EAAE;AAC1F,YAAM,KAAK,iBAAiB,KAAK;AACjC,YAAM,eAAe,eAAe,KAAK;AACzC,UAAI,CAAC,KAAK,WAAW,GAAG;AACtB,aAAK,UAAU,SAAS,aAAa,cAAc,OAAO,KAAK;AAAA,MACjE;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,eAAe,SAAyD;AACpF,SAAK,UAAU,gBAAgB,2BAA2B,OAAO,KAAK;AACtE,UAAM,KAAK,aAAa,iBAAiB,KAAK,QAAQ,MAAM;AAC5D,QAAI,KAAK,WAAW,GAAG;AACrB;AAAA,IACF;AACA,SAAK,UAAU,sBAAsB,sCAAsC,OAAO,KAAK;AACvF,SAAK,uBAAuB,MAAM,KAAK,aAAa,sBAAsB,KAAK,QAAQ,MAAM,CAAC;AAC9F,QAAI,KAAK,WAAW,GAAG;AACrB;AAAA,IACF;AACA,SAAK,UAAU,kBAAkB,kCAAkC,OAAO,KAAK;AAC/E,UAAM,SAAS,MAAM,KAAK,aAAa,oBAAoB,KAAK,QAAQ,MAAM;AAC9E,UAAM,KAAK,gBAAgB,QAAQ,OAAO;AAAA,EAC5C;AAAA,EAEA,MAAc,gBAAgB,QAA0B,SAAyD;AAC/G,QAAI,KAAK,WAAW,GAAG;AACrB,qBAAe,MAAM;AACrB;AAAA,IACF;AACA,QAAI,OAAO,WAAW,SAAS;AAC7B,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,SAAK,eAAe,OAAO;AAC3B,SAAK,kBAAkB,MAAM,KAAK,aAAa,iBAAiB,OAAO,OAAO,SAAS;AACvF,SAAK,UAAU,aAAa,uCAAuC,OAAO,KAAK;AAC/E,UAAM,KAAK,mBAAmB,OAAO;AACrC,SAAK,aAAa,QAAQ,YAAY;AACtC,SAAK,UAAU,aAAa,wCAAwC,MAAM,KAAK;AAAA,EACjF;AAAA,EAEA,MAAc,mBAAmB,SAAyD;AACxF,UAAM,KAAK,iBAAiB,EAAE,SAAS,uBAAuB;AAAA,MAC5D,OAAO,KAAK,QAAQ,OAAO;AAAA,MAC3B,UAAU,OAAO,KAAK,QAAQ,OAAO,iBAAiB,CAAC;AAAA,MACvD,gBAAgB,QAAQ;AAAA,MACxB,oBAAoB,QAAQ;AAAA,MAC5B,qBAAqB,QAAQ;AAAA,MAC7B,cAAc,QAAQ;AAAA,MACtB,WAAW,QAAQ;AAAA,IACrB,CAAC,GAAG,2BAA2B;AAAA,EACjC;AAAA,EAEQ,aAAa,cAA4B;AAC/C,SAAK,YAAY;AACjB,SAAK,2BAA2B;AAChC,SAAK,YAAY,KAAK,aAAa,YAAY,MAAM;AACnD,WAAK,KAAK,iBAAiB,YAAY;AAAA,IACzC,GAAG,iBAAiB;AAAA,EACtB;AAAA,EAEA,MAAc,iBAAiB,cAAqC;AAClE,QAAI,KAAK,iBAAiB,KAAK,oBAAoB,UAAa,KAAK,UAAU,aAAa;AAC1F;AAAA,IACF;AACA,SAAK,gBAAgB;AACrB,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,gBAAgB;AAAA,QACzC,qBAAqB,kBAAkB,+BAA+B,YAAY,CAAC;AAAA,QACnF;AAAA,MACF;AACA,WAAK,2BAA2B;AAChC,WAAK,qBAAqB,SAAS,YAAY;AAAA,IACjD,SAAS,OAAO;AACd,YAAM,KAAK,mBAAmB,KAAK;AAAA,IACrC,UAAE;AACA,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,qBAAqB,SAAkB,cAA4B;AACzE,UAAM,UAAU,iBAAiB,SAAS,EAAE,OAAO,KAAK,QAAQ,OAAO,KAAK,aAAa,CAAC;AAC1F,QAAI,QAAQ,OAAO,WAAW,GAAG;AAC/B;AAAA,IACF;AACA,SAAK,OAAO,KAAK,GAAG,QAAQ,MAAM;AAClC,SAAK,OAAO,OAAO,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,SAAS,kBAAkB,CAAC;AAC1E,SAAK,QAAQ,WAAW,QAAQ,MAAM;AACtC,SAAK,QAAQ,YAAY,kBAAkB,KAAK,MAAM,CAAC;AAAA,EACzD;AAAA,EAEA,MAAc,mBAAmB,OAA+B;AAC9D,QAAI,kBAAkB,KAAK,GAAG;AAC5B,WAAK,4BAA4B;AACjC,UAAI,KAAK,2BAA2B,2BAA2B;AAC7D,aAAK,IAAI,kCAAkC,KAAK,QAAQ,OAAO,GAAG,eAAe,OAAO,KAAK,wBAAwB,CAAC,IAAI,OAAO,yBAAyB,CAAC,IAAI;AAC/J;AAAA,MACF;AAAA,IACF;AACA,SAAK,IAAI,gCAAgC,KAAK,QAAQ,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,EAAE;AACzF,UAAM,KAAK,iBAAiB,KAAK;AACjC,SAAK,UAAU,SAAS,2CAA2C,OAAO,IAAI;AAAA,EAChF;AAAA,EAEA,MAAc,iBAAiB,sBAAiD;AAC9E,SAAK,YAAY;AACjB,SAAK,2BAA2B;AAChC,UAAM,cAAc,MAAM,KAAK,kBAAkB,oBAAoB;AACrE,UAAM,KAAK,qBAAqB;AAChC,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,uBAAsC;AAClD,UAAM,SAAS,KAAK;AACpB,SAAK,kBAAkB;AACvB,QAAI;AACF,YAAM,QAAQ,MAAM;AAAA,IACtB,SAAS,OAAO;AACd,WAAK,IAAI,yCAAyC,KAAK,QAAQ,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,EAAE;AAAA,IACpG;AAAA,EACF;AAAA,EAEQ,aAAmB;AACzB,UAAM,SAAS,KAAK;AACpB,SAAK,eAAe;AACpB,QAAI;AACF,cAAQ,KAAK;AAAA,IACf,SAAS,OAAO;AACd,WAAK,IAAI,wCAAwC,KAAK,QAAQ,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,EAAE;AAAA,IACnG;AAAA,EACF;AAAA,EAEA,MAAc,kBAAkB,sBAAiD;AAC/E,QAAI,KAAK,oBAAoB,QAAW;AACtC,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,KAAK,gBAAgB,SAAS,oBAAoB,EAAE,qBAAqB,CAAC,GAAG,2BAA2B;AAC9G,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,IAAI,iCAAiC,KAAK,QAAQ,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,EAAE;AAC1F,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,cAAoB;AAC1B,QAAI,KAAK,cAAc,QAAW;AAChC;AAAA,IACF;AACA,SAAK,aAAa,cAAc,KAAK,SAAS;AAC9C,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,UAAU,OAAqC,SAAiB,sBAA+B,sBAAqC;AAC1I,SAAK,QAAQ;AACb,SAAK,QAAQ,UAAU;AAAA,MACrB;AAAA,MACA,KAAK,KAAK,QAAQ,OAAO;AAAA,MACzB,UAAU,OAAO,KAAK,QAAQ,OAAO,iBAAiB,CAAC;AAAA,MACvD;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,mBAA2C;AACjD,QAAI,KAAK,oBAAoB,QAAW;AACtC,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,aAAsB;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,IAAI,SAAuB;AACjC,SAAK,QAAQ,QAAQ,OAAO;AAAA,EAC9B;AAAA,EAEQ,uBAAuB,QAAgD;AAC7E,UAAM,aAAa,gCAAgC,MAAM;AACzD,QAAI,WAAW,WAAW,SAAS;AACjC;AAAA,IACF;AACA,UAAM,SAAS,WAAW,WAAW,SAAY,KAAK,KAAK,WAAW,MAAM;AAC5E,SAAK,IAAI,gDAAgD,KAAK,QAAQ,OAAO,GAAG,GAAG,MAAM,EAAE;AAAA,EAC7F;AACF;AAEA,IAAM,wBAAN,cAAoC,MAAM;AAAA,EACjC,YACL,SACgB,cAChB,OACA;AACA,UAAM,SAAS,UAAU,SAAY,SAAY,EAAE,MAAM,CAAC;AAH1C;AAAA,EAIlB;AAAA,EAJkB;AAKpB;AAEA,SAAS,oBAAoB,SAAiE;AAC5F,SAAO;AAAA,IACL,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,oBAAoB,QAAQ,sBAAsB;AAAA,IAClD,qBAAqB,QAAQ,uBAAuB;AAAA,IACpD,cAAc,QAAQ,gBAAgB;AAAA,IACtC,kBAAkB,QAAQ,oBAAoB;AAAA,EAChD;AACF;AAEA,SAAS,eAAe,QAAgC;AACtD,MAAI,OAAO,WAAW,SAAS;AAC7B,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;AAEA,SAAS,+BAA+B,cAA8B;AACpE,SAAO,eAAe,IAAI,KAAK,IAAI,cAAc,0BAA0B,IAAI;AACjF;AAEA,SAAS,kBAAkB,OAAyB;AAClD,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,SAAO,QAAQ,SAAS,4BAA4B;AACtD;AAEA,SAAS,eAAe,OAAuC;AAC7D,MAAI,iBAAiB,uBAAuB;AAC1C,WAAO;AAAA,EACT;AACA,SAAO,IAAI;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,gCAAgC,QAAkE;AACzG,SAAO,OAAO,WAAW,YACrB,EAAE,QAAQ,SAAS,UAAU,YAAY,IACzC;AACN;AAEA,SAAS,YAAY,OAAwB;AAC3C,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,SAAO,QAAQ,KAAK,EAAE,SAAS,IAAI,QAAQ,KAAK,IAAI;AACtD;;;AC7TO,SAASC,iBAAgB,OAAiB,KAAqD;AACpG,qBAAmB,KAAK;AACxB,QAAM,SAAS,YAAY,OAAO,GAAG;AACrC,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL,gBAAgB,MAAM,mBAAmB;AAAA,MACzC,oBAAoB,MAAM,uBAAuB;AAAA,MACjD,qBAAqB,MAAM,wBAAwB;AAAA,MACnD,cAAc,eAAe,MAAM,YAAY;AAAA,MAC/C,kBAAkB;AAAA,IACpB;AAAA,IACA,QAAQ,YAAY,KAAK;AAAA,IACzB,QAAQ,YAAY,MAAM,MAAM;AAAA,IAChC,iBAAiB,MAAM,oBAAoB;AAAA,IAC3C,OAAO,MAAM,UAAU;AAAA,EACzB;AACF;AAEA,eAAsB,iCACpB,OACA,KACqB;AACrB,SAAOA,iBAAgB,MAAM,0BAA0B,OAAO,GAAG,GAAG,GAAG;AACzE;AAEO,SAAS,qBAAqB,KAAyB,OAAmC;AAC/F,MAAI,QAAQ,QAAW;AACrB,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,OAAO,SAAS,KAAK,EAAE;AACrC,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,SAAS,KAAK,OAAO,KAAK,MAAM,IAAI,KAAK,GAAG;AAC1E,UAAM,IAAI,MAAM,WAAW,KAAK,MAAM,GAAG,uCAAkC;AAAA,EAC7E;AACA,SAAO;AACT;AAEA,eAAe,0BACb,OACA,KACmB;AACnB,MAAI,CAAC,mBAAmB,KAAK,GAAG;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,MAAM,oBAAoB,iBAAiB,OAAO,GAAG,CAAC,EAAE,MAAM,CAAC,UAAmB;AAChG,UAAM,IAAI;AAAA,MACR;AAAA,MACA,EAAE,OAAO,MAAM;AAAA,IACjB;AAAA,EACF,CAAC;AACD,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,iBAAiB,OAAO,OAAO;AAAA,IAClC,KAAK,eAAe,MAAM,KAAK,QAAQ,OAAO;AAAA,IAC9C,OAAO,eAAe,MAAM,OAAO,QAAQ,SAAS;AAAA,EACtD;AACF;AAEA,SAAS,iBAAiB,OAAiB,KAAiF;AAC1H,QAAM,UAAU,MAAM,aAAa,IAAI,sBAAsB;AAC7D,QAAM,UAAsC;AAAA,IAC1C,GAAI,YAAY,SAAY,CAAC,IAAI,EAAE,QAAQ;AAAA,IAC3C,GAAI,MAAM,WAAW,SAAY,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,MAAM,OAAO,EAAE;AAAA,EACzE;AACA,SAAO,QAAQ,YAAY,UAAa,QAAQ,QAAQ,SAAY,SAAY;AAClF;AAEA,SAAS,iBACP,OACA,SAC0C;AAC1C,MAAI,QAAQ,MAAM,MAAM,KAAK,QAAQ,MAAM,WAAW,GAAG;AACvD,WAAO,CAAC;AAAA,EACV;AACA,SAAO,QAAQ,cAAc,SACzB,EAAE,aAAa,QAAQ,YAAY,IACnC,EAAE,QAAQ,QAAQ,UAAU;AAClC;AAEA,SAAS,mBAAmB,OAA0B;AACpD,SAAQ,CAAC,QAAQ,MAAM,MAAM,KAAK,CAAC,QAAQ,MAAM,WAAW,KAAM,CAAC,QAAQ,MAAM,GAAG,KAAK,CAAC,QAAQ,MAAM,KAAK;AAC/G;AAEA,SAAS,QAAQ,OAAoC;AACnD,SAAO,UAAU,UAAa,MAAM,KAAK,EAAE,SAAS;AACtD;AAEA,SAAS,eAAe,OAA2B,UAA0B;AAC3E,QAAM,UAAU,OAAO,KAAK;AAC5B,SAAO,YAAY,UAAa,QAAQ,WAAW,IAAI,WAAW;AACpE;AAEA,SAAS,YAAY,OAAiB,KAA4D;AAChG,QAAM,UAAU,MAAM,gBAAgB,SAAY,EAAE,QAAQ,YAAY,MAAM,QAAQ,UAAU,EAAE,IAAI,EAAE,aAAa,YAAY,MAAM,aAAa,gBAAgB,EAAE;AACtK,SAAO;AAAA,IACL,GAAG;AAAA,IACH,KAAK,YAAY,MAAM,KAAK,OAAO;AAAA,IACnC,OAAO,YAAY,MAAM,OAAO,SAAS;AAAA,IACzC,KAAK,YAAY,MAAM,KAAK,OAAO;AAAA,IACnC,OAAO,kBAAkB,MAAM,OAAO,KAAK,WAAW;AAAA,IACtD,UAAU,kBAAkB,MAAM,UAAU,KAAK,cAAc;AAAA,IAC/D,eAAe,mBAAmB,MAAM,QAAQ;AAAA,IAChD,GAAI,MAAM,WAAW,SAAY,CAAC,IAAI,EAAE,WAAW,YAAY,MAAM,QAAQ,WAAW,EAAE;AAAA,IAC1F,GAAI,MAAM,cAAc,SAAY,CAAC,IAAI,EAAE,SAAS,YAAY,MAAM,WAAW,cAAc,EAAE;AAAA,EACnG;AACF;AAEA,SAAS,YAAY,OAAuC;AAC1D,QAAM,WAAW,qBAAqB,MAAM,UAAU,YAAY;AAClE,QAAM,YAAY,qBAAqB,MAAM,WAAW,cAAc;AACtE,SAAO;AAAA,IACL,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,YAAY,WAAW,IAAK;AAAA,IAChE,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,UAAU;AAAA,EACjD;AACF;AAEA,SAAS,mBAAmB,OAAuB;AACjD,QAAM,YAAY,MAAM,WAAW,UAAa,MAAM,OAAO,KAAK,EAAE,SAAS;AAC7E,QAAM,SAAS,MAAM,gBAAgB,UAAa,MAAM,YAAY,KAAK,EAAE,SAAS;AACpF,MAAI,CAAC,aAAa,CAAC,QAAQ;AACzB,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACF;AAEA,SAAS,YAAY,OAA2B,OAAuB;AACrE,MAAI,UAAU,UAAa,MAAM,KAAK,EAAE,WAAW,GAAG;AACpD,UAAM,IAAI,MAAM,GAAG,KAAK,eAAe;AAAA,EACzC;AACA,SAAO,MAAM,KAAK;AACpB;AAEA,SAAS,kBAAkB,OAA2B,KAAyC,SAAyB;AACtH,QAAM,cAAc,OAAO,KAAK;AAChC,MAAI,gBAAgB,UAAa,YAAY,SAAS,GAAG;AACvD,WAAO;AAAA,EACT;AACA,QAAM,WAAW,IAAI,OAAO,GAAG,KAAK;AACpC,MAAI,aAAa,UAAa,SAAS,SAAS,GAAG;AACjD,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,0CAA0C,OAAO,EAAE;AACrE;AAEA,SAAS,mBAAmB,OAAmC;AAC7D,QAAM,SAAS,UAAU,SAAY,SAAY,wBAAwB,OAAO,YAAY;AAC5F,SAAO,UAAU;AACnB;AAEA,SAAS,eAAe,OAAmC;AACzD,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,SAAO,wBAAwB,OAAO,kBAAkB;AAC1D;AAEA,SAAS,wBAAwB,KAAa,OAAuB;AACnE,QAAM,QAAQ,OAAO,SAAS,KAAK,EAAE;AACrC,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,OAAO,KAAK,MAAM,IAAI,KAAK,GAAG;AACzE,UAAM,IAAI,MAAM,WAAW,KAAK,MAAM,GAAG,2CAAsC;AAAA,EACjF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAAyC;AAC5D,MAAI,UAAU,UAAa,UAAU,UAAU;AAC7C,WAAO;AAAA,EACT;AACA,MAAI,UAAU,aAAa,UAAU,QAAQ;AAC3C,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,sBAAsB,KAAK,6CAAwC;AACrF;;;ACzNA,OAAOC,cAAa;AAIb,SAAS,UAAU,OAAsB;AAC9C,EAAAA,SAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,CAAI;AAC5D;AAEO,SAAS,cAAc,OAAsB;AAClD,EAAAA,SAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI;AACnD;AAEO,SAAS,cAAc,OAAkC;AAC9D,EAAAA,SAAQ,OAAO,MAAM,mBAAmB,MAAM,KAAK,KAAK,MAAM,OAAO;AAAA,CAAI;AAC3E;AAEO,SAAS,SAAS,SAAuB;AAC9C,EAAAA,SAAQ,OAAO,MAAM,mBAAmB,OAAO;AAAA,CAAI;AACrD;AAEO,SAAS,iBAAiB,OAA6B;AAC5D,QAAM,SAAS,MAAM,WAAW,OAAO,MAAM,OAAO,MAAM,MAAM;AAChE,QAAM,WAAW,MAAM,eAAe,OAAO,MAAM,GAAG,MAAM,WAAW,SAAS,CAAC;AACjF,EAAAA,SAAQ,OAAO,MAAM,GAAG,MAAM,SAAS,IAAI,MAAM,MAAM,IAAI,MAAM,aAAa,IAAI,MAAM,IAAI,QAAQ;AAAA,CAAI;AAC1G;;;ATbA,eAAsB,KAAK,MAAwC;AACjE,QAAM,UAAU,IAAI,QAAQ;AAC5B,UACG,KAAK,eAAe,EACpB,YAAY,sGAAsG,EAClH,OAAO,sBAAsB,4CAA4C,EACzE,OAAO,wBAAwB,0BAA0B,EACzD,OAAO,oBAAoB,0CAA0C,EACrE,OAAO,sBAAsB,4CAA4C,EACzE,eAAe,oBAAoB,aAAa,EAChD,OAAO,mBAAmB,gCAAgC,EAC1D,OAAO,sBAAsB,sCAAsC,EACnE,OAAO,0BAA0B,oCAAoC,EACrE,OAAO,mBAAmB,oDAAoD,EAC9E,OAAO,uBAAuB,gCAAgC,EAC9D,OAAO,wBAAwB,sBAAsB,EACrD,OAAO,wBAAwB,2BAA2B,EAC1D,OAAO,4BAA4B,8EAA8E,MAAM,EACvH,OAAO,wBAAwB,yCAAyC,EACxE,OAAO,6BAA6B,sCAAsC,EAC1E,OAAO,8BAA8B,uCAAuC,EAC5E,OAAO,0BAA0B,6DAA6D,EAC9F,OAAO,qBAAqB,wCAAwC,QAAQ,EAC5E,OAAO,WAAW,sCAAsC,EACxD,OAAO,OAAO,UAAmC;AAChD,UAAM,gBAAgB,MAAM,iCAAiC,OAAOC,SAAQ,GAAG,CAAC;AAAA,EAClF,CAAC;AAEH,QAAM,QAAQ,WAAW,CAAC,GAAG,IAAI,CAAC;AACpC;AAEA,eAAsB,gBAAgB,SAAoC;AACxE,QAAM,SAAS,MAAM,cAAc,OAAO;AAC1C,MAAI;AACF,UAAM,SAA2B,CAAC;AAClC,UAAM,aAAa,iBAAiB,OAAO;AAC3C,UAAM,eAAe,6BAA6B;AAClD,UAAM,UAAU,IAAI,iBAAiB;AAAA,MACnC,QAAQ,EAAE,GAAG,QAAQ,QAAQ,WAAW,OAAO,KAAK;AAAA,MACpD,SAAS,CAAC,UAAU;AAClB,YAAI,CAAC,QAAQ,OAAO;AAClB,wBAAc,KAAK;AAAA,QACrB;AACA,qBAAa,OAAO,KAAK;AAAA,MAC3B;AAAA,MACA,OAAO,CAAC,YAAY;AAClB,YAAI,CAAC,QAAQ,OAAO;AAClB,mBAAS,OAAO;AAAA,QAClB;AAAA,MACF;AAAA,MACA,UAAU,CAAC,UAAU;AACnB,qBAAa,OAAO,SAAS,MAAM;AACnC,mBAAW,MAAM,OAAO,MAAM;AAAA,MAChC;AAAA,IACF,CAAC;AACD,UAAM,gBAAgB,SAAS,SAAS,YAAY,YAAY;AAChE,QAAI,QAAQ,WAAW,QAAQ;AAC7B,gBAAU,EAAE,OAAO,CAAC;AAAA,IACtB;AAAA,EACF,UAAE;AACA,UAAM,OAAO,QAAQ;AAAA,EACvB;AACF;AAEA,SAAS,aAAa,OAAkC,SAAqB,QAAgC;AAC3G,aAAW,SAAS,OAAO;AACzB,WAAO,KAAK,KAAK;AACjB,QAAI,QAAQ,WAAW,UAAU;AAC/B,oBAAc,KAAK;AAAA,IACrB;AACA,QAAI,QAAQ,WAAW,WAAW;AAChC,uBAAiB,KAAK;AAAA,IACxB;AAAA,EACF;AACF;AAEA,eAAe,gBACb,SACA,SACA,YACA,cACe;AACf,QAAM,QAAQ,mBAAmB;AACjC,QAAM,WAAW,yBAAyB,QAAQ,OAAO,UAAU;AACnE,MAAI,aAAkC;AACtC,MAAI,SAAS;AACb,MAAI;AACF,UAAM,QAAQ,MAAM,QAAQ,KAAK;AACjC,iBAAa,MAAM,YAAY,CAAC,OAAO,YAAY,UAAU,YAAY,CAAC;AAAA,EAC5E,SAAS,OAAO;AACd,aAAS;AACT,UAAM;AAAA,EACR,UAAE;AACA,UAAM,QAAQ;AACd,aAAS,QAAQ;AACjB,eAAW,QAAQ;AACnB,iBAAa,QAAQ;AACrB,UAAM,QAAQ,KAAK,EAAE,sBAAsB,QAAQ,iBAAiB,QAAQ,SAAS,UAAU,WAAW,CAAC;AAAA,EAC7G;AACF;AAWA,eAAe,YAAY,SAA8D;AACvF,SAAO,MAAM,QAAQ,KAAK,QAAQ,IAAI,CAAC,WAAW,OAAO,OAAO,CAAC;AACnE;AAEA,SAAS,yBAAyB,YAA4C;AAC5E,MAAI,eAAe,QAAW;AAC5B,WAAO,sBAAsB;AAAA,EAC/B;AACA,MAAI;AACJ,QAAM,UAAU,IAAI,QAA6B,CAAC,YAAY;AAC5D,YAAQ,WAAW,MAAM;AACvB,cAAQ,UAAU;AAAA,IACpB,GAAG,UAAU;AAAA,EACf,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA,SAAS,MAAY;AACnB,UAAI,UAAU,QAAW;AACvB,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,qBAAuG;AAC9G,MAAI,cAAqD,MAAM;AAC7D;AAAA,EACF;AACA,QAAM,UAAU,IAAI,QAA6B,CAAC,YAAY;AAC5D,kBAAc;AAAA,EAChB,CAAC;AACD,QAAM,WAAW,MAAY;AAC3B,gBAAY,MAAM;AAAA,EACpB;AACA,EAAAA,SAAQ,KAAK,UAAU,QAAQ;AAC/B,EAAAA,SAAQ,KAAK,WAAW,QAAQ;AAChC,SAAO;AAAA,IACL;AAAA,IACA,SAAS,MAAY;AACnB,MAAAA,SAAQ,IAAI,UAAU,QAAQ;AAC9B,MAAAA,SAAQ,IAAI,WAAW,QAAQ;AAAA,IACjC;AAAA,EACF;AACF;AAEA,SAAS,wBAAoC;AAC3C,SAAO;AAAA,IACL,SAAS,IAAI,QAA6B,MAAM;AAC9C;AAAA,IACF,CAAC;AAAA,IACD,SAAS,MAAY;AACnB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,+BAAuD;AAC9D,MAAI,cAAc;AAClB,MAAI,UAAU;AACd,MAAI,aAAqC,MAAM;AAC7C;AAAA,EACF;AACA,QAAM,UAAU,IAAI,QAA6B,CAAC,UAAU,WAAW;AACrE,iBAAa;AAAA,EACf,CAAC;AACD,UAAQ,MAAM,MAAM;AAClB;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,CAAC,UAAgB;AACvB,UAAI,MAAM,UAAU,aAAa;AAC/B,sBAAc;AACd;AAAA,MACF;AACA,UAAI,MAAM,UAAU,WAAW,CAAC,eAAe,SAAS;AACtD;AAAA,MACF;AACA,gBAAU;AACV,iBAAW,IAAI,MAAM,MAAM,OAAO,CAAC;AAAA,IACrC;AAAA,IACA,SAAS,MAAY;AACnB,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,SAIxB;AACA,MAAI,QAAQ,OAAO,cAAc,QAAW;AAC1C,WAAO;AAAA,MACL,GAAG,sBAAsB;AAAA,MACzB,OAAO,MAAY;AACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,eAAsD,MAAM;AAC9D;AAAA,EACF;AACA,QAAM,UAAU,IAAI,QAA6B,CAAC,YAAY;AAC5D,mBAAe;AAAA,EACjB,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA,OAAO,CAAC,UAAgB;AACtB,UAAI,QAAQ,OAAO,cAAc,UAAa,SAAS,QAAQ,OAAO,WAAW;AAC/E,qBAAa,YAAY;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,SAAS,MAAY;AACnB;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,cAAc,SAAgG;AAC3H,MAAI,QAAQ,OAAO,cAAc,QAAW;AAC1C,WAAO;AAAA,MACL,MAAM,QAAQ,OAAO;AAAA,MACrB,SAAS,MAAqB,QAAQ,QAAQ;AAAA,IAChD;AAAA,EACF;AACA,QAAM,OAAO,MAAM,sBAAsB;AACzC,SAAO;AAAA,IACL;AAAA,IACA,SAAS,YAA2B;AAClC,YAAM,sBAAsB,IAAI;AAAA,IAClC;AAAA,EACF;AACF;;;AD1PA,IAAI;AACF,QAAM,KAAKC,SAAQ,IAAI;AACzB,SAAS,OAAO;AACd,EAAAA,SAAQ,OAAO,MAAM,0BAA0B,eAAe,KAAK,CAAC;AAAA,CAAI;AACxE,EAAAA,SAAQ,WAAW;AACrB;AAEA,SAAS,eAAe,OAAwB;AAC9C,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,SAAO,QAAQ,KAAK,EAAE,SAAS,IAAI,QAAQ,KAAK,IAAI;AACtD;","names":["process","process","isRecord","buildRunOptions","process","process","process"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  declare const CF_LIVE_TRACE_GLOBAL_NAME = "__SAPTOOLS_CF_LIVE_TRACE__";
2
- declare const CF_LIVE_TRACE_RUNTIME_VERSION = 1;
2
+ declare const CF_LIVE_TRACE_RUNTIME_VERSION = 2;
3
3
  interface RuntimeInstallOptions {
4
4
  readonly appId: string;
5
5
  readonly instance: string;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/runtime-source.ts
2
2
  var CF_LIVE_TRACE_GLOBAL_NAME = "__SAPTOOLS_CF_LIVE_TRACE__";
3
- var CF_LIVE_TRACE_RUNTIME_VERSION = 1;
3
+ var CF_LIVE_TRACE_RUNTIME_VERSION = 2;
4
4
  var CF_LIVE_TRACE_RUNTIME_SOURCE = `
5
5
  (() => {
6
6
  const name = '${CF_LIVE_TRACE_GLOBAL_NAME}';
@@ -197,15 +197,12 @@ var CF_LIVE_TRACE_RUNTIME_SOURCE = `
197
197
  status() {
198
198
  return { installed: state.installed, enabled: state.enabled, queueSize: state.queue.length, droppedCount: state.droppedCount, maxEvents: state.options.maxEvents };
199
199
  },
200
- uninstall() {
200
+ async uninstall() {
201
201
  state.enabled = false;
202
- const requireFn = loadRequire();
203
- if (requireFn) {
204
- const http = requireFn('http');
205
- const https = requireFn('https');
206
- if (state.originals.httpServerEmit && http && http.Server) http.Server.prototype.emit = state.originals.httpServerEmit;
207
- if (state.originals.httpsServerEmit && https && https.Server) https.Server.prototype.emit = state.originals.httpsServerEmit;
208
- }
202
+ const http = await loadModule('http');
203
+ const https = await loadModule('https');
204
+ if (state.originals.httpServerEmit && http && http.Server) http.Server.prototype.emit = state.originals.httpServerEmit;
205
+ if (state.originals.httpsServerEmit && https && https.Server) https.Server.prototype.emit = state.originals.httpsServerEmit;
209
206
  state.installed = false;
210
207
  return api.status();
211
208
  }
@@ -521,6 +518,8 @@ function spawnPortForward(params) {
521
518
  env: buildCfEnv(params.cfHomeDir),
522
519
  stdio: ["ignore", "pipe", "pipe"]
523
520
  });
521
+ child.stdout.resume();
522
+ child.stderr.resume();
524
523
  return {
525
524
  process: child,
526
525
  localPort: params.localPort,
@@ -662,7 +661,11 @@ function extractErrorDetail(error) {
662
661
  if (stderr.length > 0) {
663
662
  return stderr;
664
663
  }
665
- return error["message"] instanceof Error ? error["message"].message : "";
664
+ const message = error["message"];
665
+ if (typeof message === "string") {
666
+ return message.trim();
667
+ }
668
+ return message instanceof Error ? message.message.trim() : "";
666
669
  }
667
670
  function formatErrorMessage(error) {
668
671
  const message = error instanceof Error ? error.message : String(error);
@@ -898,6 +901,9 @@ var LiveTraceSession = class {
898
901
  async stop(options) {
899
902
  this.stopRequested = true;
900
903
  if (!this.isRunning()) {
904
+ if (this.state === "error" && options.reason === "error") {
905
+ return;
906
+ }
901
907
  this.postState("stopped", `Trace stopped (${options.reason}).`, false, false);
902
908
  return;
903
909
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime-source.ts","../src/preview.ts","../src/payload.ts","../src/summary.ts","../src/cf.ts","../src/inspector.ts","../src/session.ts"],"sourcesContent":["export const CF_LIVE_TRACE_GLOBAL_NAME = \"__SAPTOOLS_CF_LIVE_TRACE__\";\nexport const CF_LIVE_TRACE_RUNTIME_VERSION = 1;\n\nexport interface RuntimeInstallOptions {\n readonly appId: string;\n readonly instance: string;\n readonly captureHeaders: boolean;\n readonly captureRequestBody: boolean;\n readonly captureResponseBody: boolean;\n readonly maxBodyBytes: number;\n readonly maxEvents: number;\n}\n\nexport interface StopExpressionOptions {\n readonly uninstallRuntimeHook: boolean;\n}\n\nexport const CF_LIVE_TRACE_RUNTIME_SOURCE = `\n(() => {\n const name = '${CF_LIVE_TRACE_GLOBAL_NAME}';\n const runtimeVersion = ${String(CF_LIVE_TRACE_RUNTIME_VERSION)};\n const existing = globalThis[name];\n if (existing && typeof existing.version === 'number' && existing.version >= runtimeVersion) return existing;\n if (existing && typeof existing.uninstall === 'function') {\n try {\n existing.uninstall();\n } catch {}\n }\n let BufferCtor = globalThis.Buffer;\n const state = {\n version: runtimeVersion,\n installed: false,\n enabled: false,\n options: { appId: '', instance: '0', captureHeaders: true, captureRequestBody: true, captureResponseBody: true, maxBodyBytes: 4096, maxEvents: 1000 },\n queue: [],\n droppedCount: 0,\n originals: {},\n seen: new WeakSet(),\n nextId: 1\n };\n const loadRequire = () => {\n if (typeof require === 'function') return require;\n if (globalThis.process && globalThis.process.mainModule && typeof globalThis.process.mainModule.require === 'function') {\n return globalThis.process.mainModule.require.bind(globalThis.process.mainModule);\n }\n return null;\n };\n const loadModule = async (moduleName) => {\n const requireFn = loadRequire();\n if (requireFn) return requireFn(moduleName);\n if (globalThis.process && typeof globalThis.process.getBuiltinModule === 'function') {\n return globalThis.process.getBuiltinModule(moduleName);\n }\n return await import('node:' + moduleName);\n };\n const toHeaderRecord = (headers) => {\n const output = {};\n if (!headers || !state.options.captureHeaders) return output;\n for (const key of Object.keys(headers)) {\n const value = headers[key];\n output[key] = Array.isArray(value) ? value.join(', ') : String(value);\n }\n return output;\n };\n const chunkText = (chunk) => {\n if (chunk === undefined || chunk === null) return '';\n if (BufferCtor && BufferCtor.isBuffer(chunk)) return chunk.toString('utf8');\n if (typeof chunk === 'string') return chunk;\n if (chunk instanceof Uint8Array && BufferCtor) return BufferCtor.from(chunk).toString('utf8');\n return '';\n };\n const byteLength = (text) => BufferCtor ? BufferCtor.byteLength(text) : text.length;\n const appendPreview = (current, chunk, enabled) => {\n if (!enabled) return current;\n const text = chunkText(chunk);\n if (state.options.maxBodyBytes <= 0) return current + text;\n if (current.length >= state.options.maxBodyBytes) return current;\n return (current + text).slice(0, state.options.maxBodyBytes);\n };\n const enqueue = (event) => {\n if (state.queue.length >= state.options.maxEvents) {\n state.queue.shift();\n state.droppedCount += 1;\n }\n state.queue.push(event);\n };\n const observe = (req, res) => {\n if (!state.enabled || !req || !res || state.seen.has(req)) return;\n state.seen.add(req);\n const started = Date.now();\n const initialUrl = String(req.url || '');\n const traceId = String(state.nextId++);\n let requestBytes = 0;\n let responseBytes = 0;\n let requestPreview = '';\n let responsePreview = '';\n let finished = false;\n const originalReqEmit = req.emit;\n const originalWrite = res.write;\n const originalEnd = res.end;\n req.emit = function patchedReqEmit(eventName, ...args) {\n if (eventName === 'data' && args[0] !== undefined) {\n const text = chunkText(args[0]);\n requestBytes += byteLength(text);\n requestPreview = appendPreview(requestPreview, args[0], state.options.captureRequestBody);\n }\n return originalReqEmit.apply(this, [eventName, ...args]);\n };\n res.write = function patchedWrite(chunk, ...args) {\n const text = chunkText(chunk);\n responseBytes += byteLength(text);\n responsePreview = appendPreview(responsePreview, chunk, state.options.captureResponseBody);\n return originalWrite.apply(this, [chunk, ...args]);\n };\n res.end = function patchedEnd(chunk, ...args) {\n if (chunk !== undefined) {\n const text = chunkText(chunk);\n responseBytes += byteLength(text);\n responsePreview = appendPreview(responsePreview, chunk, state.options.captureResponseBody);\n }\n return originalEnd.apply(this, [chunk, ...args]);\n };\n const finish = () => {\n if (finished) return;\n finished = true;\n req.emit = originalReqEmit;\n res.write = originalWrite;\n res.end = originalEnd;\n const rawUrl = initialUrl || String(req.url || '');\n enqueue({\n id: traceId,\n timestamp: new Date().toISOString(),\n instance: state.options.instance,\n method: String(req.method || 'GET').toUpperCase(),\n path: rawUrl.split('?')[0] || rawUrl,\n url: rawUrl,\n normalizedUrl: rawUrl,\n status: typeof res.statusCode === 'number' ? res.statusCode : null,\n durationMs: Date.now() - started,\n requestBytes,\n responseBytes,\n requestHeaders: toHeaderRecord(req.headers),\n responseHeaders: toHeaderRecord(typeof res.getHeaders === 'function' ? res.getHeaders() : {}),\n requestBodyPreview: requestPreview,\n responseBodyPreview: responsePreview,\n requestBodyTruncated: state.options.maxBodyBytes > 0 && requestPreview.length >= state.options.maxBodyBytes,\n responseBodyTruncated: state.options.maxBodyBytes > 0 && responsePreview.length >= state.options.maxBodyBytes,\n droppedBeforeEvent: state.droppedCount,\n traceId,\n correlationId: req.headers && typeof req.headers['x-saptools-trace-id'] === 'string' ? req.headers['x-saptools-trace-id'] : null\n });\n };\n res.once('finish', finish);\n res.once('close', finish);\n };\n const patchEmit = (serverPrototype) => {\n if (!serverPrototype || serverPrototype.emit.__saptoolsCfLiveTracePatched) return undefined;\n const original = serverPrototype.emit;\n const patched = function patchedServerEmit(eventName, ...args) {\n if (eventName === 'request') observe(args[0], args[1]);\n return original.apply(this, [eventName, ...args]);\n };\n patched.__saptoolsCfLiveTracePatched = true;\n serverPrototype.emit = patched;\n return original;\n };\n const toTransportLimit = (value) => {\n const numeric = Number(value);\n return Number.isFinite(numeric) && numeric > 0 ? Math.floor(numeric) : 0;\n };\n const limitPreview = (event, previewKey, truncatedKey, maxChars) => {\n const preview = event[previewKey];\n if (maxChars <= 0 || typeof preview !== 'string' || preview.length <= maxChars) return event;\n return { ...event, [previewKey]: preview.slice(0, maxChars), [truncatedKey]: true };\n };\n const eventForDrain = (event, maxChars) => {\n if (!event || typeof event !== 'object') return event;\n let output = { ...event };\n output = limitPreview(output, 'requestBodyPreview', 'requestBodyTruncated', maxChars);\n output = limitPreview(output, 'responseBodyPreview', 'responseBodyTruncated', maxChars);\n return output;\n };\n const api = {\n version: runtimeVersion,\n async install(options) {\n state.options = { ...state.options, ...options };\n if (!state.installed) {\n if (!BufferCtor) {\n const bufferModule = await loadModule('buffer');\n BufferCtor = bufferModule && bufferModule.Buffer ? bufferModule.Buffer : BufferCtor;\n }\n const http = await loadModule('http');\n const https = await loadModule('https');\n state.originals.httpServerEmit = patchEmit(http && http.Server && http.Server.prototype);\n state.originals.httpsServerEmit = patchEmit(https && https.Server && https.Server.prototype);\n state.installed = true;\n }\n state.enabled = true;\n return api.status();\n },\n disable() {\n state.enabled = false;\n return api.status();\n },\n drainEvents(maxCount, maxTransportBodyBytes) {\n const count = Math.max(0, Math.min(Number(maxCount) || 0, state.queue.length));\n const transportLimit = toTransportLimit(maxTransportBodyBytes);\n const events = state.queue.splice(0, count).map((event) => eventForDrain(event, transportLimit));\n return { events, droppedCount: state.droppedCount, queueSize: state.queue.length };\n },\n status() {\n return { installed: state.installed, enabled: state.enabled, queueSize: state.queue.length, droppedCount: state.droppedCount, maxEvents: state.options.maxEvents };\n },\n uninstall() {\n state.enabled = false;\n const requireFn = loadRequire();\n if (requireFn) {\n const http = requireFn('http');\n const https = requireFn('https');\n if (state.originals.httpServerEmit && http && http.Server) http.Server.prototype.emit = state.originals.httpServerEmit;\n if (state.originals.httpsServerEmit && https && https.Server) https.Server.prototype.emit = state.originals.httpsServerEmit;\n }\n state.installed = false;\n return api.status();\n }\n };\n globalThis[name] = api;\n return api;\n})()\n`;\n\nexport function buildInstallExpression(options: RuntimeInstallOptions): string {\n return `${CF_LIVE_TRACE_RUNTIME_SOURCE}.install(${JSON.stringify(options)})`;\n}\n\nexport function buildDrainExpression(maxCount: number, maxTransportBodyBytes: number): string {\n return `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.drainEvents(${String(maxCount)}, ${String(maxTransportBodyBytes)}) ?? { events: [], droppedCount: 0, queueSize: 0 }`;\n}\n\nexport function buildStopExpression(options: StopExpressionOptions): string {\n return options.uninstallRuntimeHook\n ? `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.uninstall() ?? { installed: false, enabled: false }`\n : `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.disable() ?? { installed: false, enabled: false }`;\n}\n","export interface PreviewTruncationResult {\n readonly preview: string;\n readonly truncated: boolean;\n}\n\nexport function truncatePreview(preview: string, maxChars: number): PreviewTruncationResult {\n if (maxChars <= 0) {\n return { preview, truncated: false };\n }\n if (preview.length <= maxChars) {\n return { preview, truncated: false };\n }\n return { preview: preview.slice(0, maxChars), truncated: true };\n}\n","import { truncatePreview } from \"./preview.js\";\nimport type { DrainParseResult, LiveTraceEvent } from \"./types.js\";\n\nexport interface DrainParseOptions {\n readonly appId: string;\n readonly maxBodyBytes: number;\n}\n\nlet fallbackEventId = 0;\n\nexport function parseDrainResult(payload: unknown, options: DrainParseOptions): DrainParseResult {\n if (!isRecord(payload)) {\n return { events: [], droppedCount: 0, queueSize: 0 };\n }\n const rawEvents = Array.isArray(payload[\"events\"]) ? payload[\"events\"] : [];\n return {\n events: rawEvents\n .map((event) => parseRuntimeEvent(event, options))\n .filter((event): event is LiveTraceEvent => event !== null),\n droppedCount: readNonNegativeNumber(payload[\"droppedCount\"]),\n queueSize: readNonNegativeNumber(payload[\"queueSize\"]),\n };\n}\n\nfunction parseRuntimeEvent(payload: unknown, options: DrainParseOptions): LiveTraceEvent | null {\n if (!isRecord(payload)) {\n return null;\n }\n const rawUrl = readString(payload[\"url\"]) ?? readString(payload[\"normalizedUrl\"]) ?? readString(payload[\"path\"]);\n if (rawUrl === null) {\n return null;\n }\n const requestBody = limitBodyPreview(readString(payload[\"requestBodyPreview\"]) ?? \"\", options.maxBodyBytes);\n const responseBody = limitBodyPreview(readString(payload[\"responseBodyPreview\"]) ?? \"\", options.maxBodyBytes);\n return buildEvent(payload, rawUrl, requestBody, responseBody, options);\n}\n\nfunction buildEvent(\n payload: Record<string, unknown>,\n rawUrl: string,\n requestBody: { readonly preview: string; readonly truncated: boolean },\n responseBody: { readonly preview: string; readonly truncated: boolean },\n options: DrainParseOptions,\n): LiveTraceEvent {\n return {\n id: readString(payload[\"id\"]) ?? nextFallbackEventId(),\n timestamp: readString(payload[\"timestamp\"]) ?? new Date().toISOString(),\n appId: options.appId,\n instance: readString(payload[\"instance\"]) ?? \"0\",\n method: (readString(payload[\"method\"]) ?? \"GET\").toUpperCase(),\n path: readString(payload[\"path\"]) ?? normalizePath(rawUrl),\n url: rawUrl,\n normalizedUrl: readString(payload[\"normalizedUrl\"]) ?? normalizePath(rawUrl),\n status: readNullableNumber(payload[\"status\"]),\n durationMs: readNullableNumber(payload[\"durationMs\"]),\n requestBytes: readNonNegativeNumber(payload[\"requestBytes\"]),\n responseBytes: readNonNegativeNumber(payload[\"responseBytes\"]),\n requestHeaders: readHeaders(payload[\"requestHeaders\"]),\n responseHeaders: readHeaders(payload[\"responseHeaders\"]),\n requestBodyPreview: requestBody.preview,\n responseBodyPreview: responseBody.preview,\n requestBodyTruncated: payload[\"requestBodyTruncated\"] === true || requestBody.truncated,\n responseBodyTruncated: payload[\"responseBodyTruncated\"] === true || responseBody.truncated,\n droppedBeforeEvent: readNonNegativeNumber(payload[\"droppedBeforeEvent\"]),\n source: \"runtime-http\",\n traceId: readString(payload[\"traceId\"]) ?? readString(payload[\"id\"]) ?? \"\",\n correlationId: readString(payload[\"correlationId\"]),\n };\n}\n\nfunction readHeaders(value: unknown): Record<string, string> {\n if (!isRecord(value)) {\n return {};\n }\n const headers: Record<string, string> = {};\n for (const [key, rawValue] of Object.entries(value)) {\n const header = readHeaderValue(rawValue);\n if (header !== null) {\n headers[key] = header;\n }\n }\n return headers;\n}\n\nfunction readHeaderValue(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item)).join(\", \");\n }\n return null;\n}\n\nfunction limitBodyPreview(preview: string, maxChars: number): { readonly preview: string; readonly truncated: boolean } {\n return truncatePreview(preview, maxChars);\n}\n\nfunction normalizePath(rawUrl: string): string {\n try {\n const parsed = new URL(rawUrl, \"https://saptools.local\");\n return `${parsed.pathname}${parsed.search}`;\n } catch {\n return rawUrl;\n }\n}\n\nfunction readString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction readNullableNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction readNonNegativeNumber(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? value : 0;\n}\n\nfunction nextFallbackEventId(): string {\n fallbackEventId += 1;\n return `runtime-${String(fallbackEventId)}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { LiveTraceEvent, LiveTraceUrlSummary } from \"./types.js\";\n\ntype StatusBucket = \"2xx\" | \"3xx\" | \"4xx\" | \"5xx\" | \"unknown\";\n\ninterface MutableSummary {\n readonly normalizedUrl: string;\n readonly displayUrl: string;\n readonly methods: Set<string>;\n totalCount: number;\n readonly statusCounts: Record<StatusBucket, number>;\n latestStatus: number | null;\n latestDurationMs: number | null;\n latestSeenAt: string;\n}\n\nexport function buildUrlSummaries(events: readonly LiveTraceEvent[]): LiveTraceUrlSummary[] {\n const summaries = new Map<string, MutableSummary>();\n for (const event of events) {\n const normalizedUrl = normalizeEventUrl(event);\n const current = summaries.get(normalizedUrl) ?? createSummary(normalizedUrl);\n updateSummary(current, event);\n summaries.set(normalizedUrl, current);\n }\n return [...summaries.values()]\n .map(toImmutableSummary)\n .sort((left, right) => right.latestSeenAt.localeCompare(left.latestSeenAt));\n}\n\nexport function normalizeEventUrl(event: LiveTraceEvent): string {\n const candidate = event.normalizedUrl.length > 0 ? event.normalizedUrl : event.url.length > 0 ? event.url : event.path;\n return normalizeUrl(candidate);\n}\n\nfunction updateSummary(summary: MutableSummary, event: LiveTraceEvent): void {\n summary.methods.add(event.method);\n summary.totalCount += 1;\n summary.statusCounts[toStatusBucket(event.status)] += 1;\n if (event.timestamp >= summary.latestSeenAt) {\n summary.latestStatus = event.status;\n summary.latestDurationMs = event.durationMs;\n summary.latestSeenAt = event.timestamp;\n }\n}\n\nfunction normalizeUrl(rawUrl: string): string {\n if (rawUrl.trim().length === 0) {\n return rawUrl;\n }\n try {\n const parsed = new URL(rawUrl, \"https://saptools.local\");\n return `${parsed.pathname}${parsed.search}`;\n } catch {\n return rawUrl;\n }\n}\n\nfunction createSummary(normalizedUrl: string): MutableSummary {\n return {\n normalizedUrl,\n displayUrl: normalizedUrl,\n methods: new Set<string>(),\n totalCount: 0,\n statusCounts: { \"2xx\": 0, \"3xx\": 0, \"4xx\": 0, \"5xx\": 0, unknown: 0 },\n latestStatus: null,\n latestDurationMs: null,\n latestSeenAt: \"\",\n };\n}\n\nfunction toImmutableSummary(summary: MutableSummary): LiveTraceUrlSummary {\n return {\n normalizedUrl: summary.normalizedUrl,\n displayUrl: summary.displayUrl,\n methods: [...summary.methods].sort(),\n totalCount: summary.totalCount,\n statusCounts: { ...summary.statusCounts },\n latestStatus: summary.latestStatus,\n latestDurationMs: summary.latestDurationMs,\n latestSeenAt: summary.latestSeenAt,\n };\n}\n\nfunction toStatusBucket(status: number | null): StatusBucket {\n if (status === null) {\n return \"unknown\";\n }\n if (status >= 200 && status < 300) {\n return \"2xx\";\n }\n if (status >= 300 && status < 400) {\n return \"3xx\";\n }\n if (status >= 400 && status < 500) {\n return \"4xx\";\n }\n if (status >= 500 && status < 600) {\n return \"5xx\";\n }\n return \"unknown\";\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { connect as netConnect, createServer } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nimport type { CfLiveTraceTarget, InspectorStartupResult, PortForwardHandle, TunnelOpenResult } from \"./types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CF_MAX_BUFFER_BYTES = 8 * 1024 * 1024;\nconst CF_COMMAND_TIMEOUT_MS = 180_000;\nconst CF_SSH_READY_TIMEOUT_MS = 60_000;\nconst INSPECTOR_SIGNAL_TIMEOUT_MS = 15_000;\nconst INSPECTOR_REMOTE_HOST = \"127.0.0.1\";\nconst INSPECTOR_REMOTE_PORT = 9229;\nconst TUNNEL_KEEPALIVE_SECONDS = 6 * 60 * 60;\nconst TUNNEL_READY_TIMEOUT_MS = 20_000;\nconst TUNNEL_READY_POLL_MS = 200;\n\nexport interface RunCfOptions {\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly envOverrides?: Record<string, string>;\n readonly timeoutMs?: number;\n readonly redactor?: (message: string) => string;\n}\n\nexport interface CfDependencies {\n runCf(args: readonly string[], options: RunCfOptions): Promise<string>;\n}\n\nexport interface TunnelDependencies {\n allocatePort(): Promise<number>;\n spawnPortForward(params: PortForwardParams): PortForwardHandle;\n waitForLocalPort(port: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean>;\n}\n\nexport interface PortForwardParams {\n readonly appName: string;\n readonly localPort: number;\n readonly remoteHost: string;\n readonly remotePort: number;\n readonly keepAliveSeconds: number;\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly instanceIndex?: number;\n}\n\nexport interface InspectorTunnelTarget {\n readonly app?: string;\n readonly appName?: string;\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly instanceIndex?: number;\n}\n\nexport async function createTemporaryCfHome(): Promise<string> {\n return await mkdtemp(join(tmpdir(), \"saptools-cf-live-trace-\"));\n}\n\nexport async function removeTemporaryCfHome(cfHomeDir: string): Promise<void> {\n await rm(cfHomeDir, { recursive: true, force: true });\n}\n\nexport async function prepareCfSession(\n target: CfLiveTraceTarget,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<void> {\n const apiEndpoint = resolveApiEndpoint(target);\n const redactor = createSecretRedactor([target.email, target.password]);\n const baseOptions = buildRunOptions(target, redactor);\n await dependencies.runCf([\"api\", apiEndpoint], baseOptions);\n await dependencies.runCf([\"auth\"], {\n ...baseOptions,\n envOverrides: { CF_USERNAME: target.email, CF_PASSWORD: target.password },\n });\n await dependencies.runCf([\"target\", \"-o\", target.org, \"-s\", target.space], baseOptions);\n}\n\nexport async function ensureSshEnabled(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<void> {\n const redactor = createSecretRedactor([target.email, target.password]);\n const options = buildRunOptions(target, redactor);\n const status = await dependencies.runCf([\"ssh-enabled\", target.app], options);\n if (parseSshStatus(status) === \"enabled\") {\n return;\n }\n await dependencies.runCf([\"enable-ssh\", target.app], options);\n await dependencies.runCf([\"restart\", target.app], options);\n await dependencies.runCf(buildCfSshArgs(target.app, target.instanceIndex, [\"-c\", \"true\"]), {\n ...options,\n timeoutMs: CF_SSH_READY_TIMEOUT_MS,\n });\n}\n\nexport async function tryStartNodeInspector(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<boolean> {\n const result = await startNodeInspector(target, dependencies);\n return result.status === \"ready\";\n}\n\nexport async function startNodeInspector(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<InspectorStartupResult> {\n const redactor = createSecretRedactor([target.email, target.password]);\n try {\n const stdout = await dependencies.runCf(\n buildCfSshArgs(target.app, target.instanceIndex, [\"-c\", buildInspectorSignalCommand()]),\n { ...buildRunOptions(target, redactor), timeoutMs: INSPECTOR_SIGNAL_TIMEOUT_MS },\n );\n return hasInspectorReadyMarker(stdout)\n ? { status: \"ready\" }\n : { status: \"not-ready\", ...optionalDetail(summarizeInspectorStartupOutput(stdout)) };\n } catch (error) {\n return { status: \"not-ready\", ...optionalDetail(redactor(formatErrorMessage(error))) };\n }\n}\n\nexport async function openInspectorTunnel(\n target: InspectorTunnelTarget,\n dependencies: TunnelDependencies = defaultTunnelDependencies,\n): Promise<TunnelOpenResult> {\n const localPort = await dependencies.allocatePort();\n const handle = dependencies.spawnPortForward(buildPortForwardParams(target, localPort));\n const ready = await raceForwardReadiness(handle, dependencies);\n if (!ready) {\n handle.stop();\n return { status: \"not-reachable\" };\n }\n return { status: \"ready\", handle };\n}\n\nexport function buildCfSshArgs(appName: string, instanceIndex: number | undefined, tail: readonly string[]): string[] {\n const args = [\"ssh\", appName];\n if (instanceIndex !== undefined) {\n args.push(\"-i\", String(instanceIndex));\n }\n return [...args, ...tail];\n}\n\nexport function buildInspectorSignalCommand(): string {\n return INSPECTOR_SIGNAL_COMMAND;\n}\n\nexport function createSecretRedactor(secrets: readonly string[]): (message: string) => string {\n const values = secrets.map((secret) => secret.trim()).filter((secret) => secret.length > 0);\n return (message: string): string => values.reduce((current, secret) => current.split(secret).join(\"<redacted>\"), message);\n}\n\nexport async function runCfCommand(args: readonly string[], options: RunCfOptions): Promise<string> {\n const command = resolveCommand(options.command);\n try {\n const { stdout } = await execFileAsync(command.bin, [...command.argsPrefix, ...args], {\n env: buildCfEnv(options.cfHomeDir, options.envOverrides),\n maxBuffer: CF_MAX_BUFFER_BYTES,\n timeout: options.timeoutMs ?? CF_COMMAND_TIMEOUT_MS,\n });\n return stdout;\n } catch (error) {\n throw new Error(formatCfError(args, error, options.redactor), { cause: error });\n }\n}\n\nexport function spawnPortForward(params: PortForwardParams): PortForwardHandle {\n const command = resolveCommand(params.command);\n const forwardSpec = `${String(params.localPort)}:${params.remoteHost}:${String(params.remotePort)}`;\n const sshArgs = buildCfSshArgs(params.appName, params.instanceIndex, [\"-L\", forwardSpec, \"-c\", `sleep ${String(params.keepAliveSeconds)}`]);\n const child = spawn(command.bin, [...command.argsPrefix, ...sshArgs], {\n env: buildCfEnv(params.cfHomeDir),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n return {\n process: child,\n localPort: params.localPort,\n stop(): void {\n if (!child.killed) {\n child.kill();\n }\n },\n };\n}\n\nexport const defaultCfDependencies: CfDependencies = {\n runCf: runCfCommand,\n};\n\nexport const defaultTunnelDependencies: TunnelDependencies = {\n allocatePort: findFreePort,\n spawnPortForward,\n waitForLocalPort,\n};\n\nfunction buildRunOptions(target: Pick<CfLiveTraceTarget, \"cfHomeDir\" | \"command\">, redactor: (message: string) => string): RunCfOptions {\n return {\n ...(target.cfHomeDir === undefined ? {} : { cfHomeDir: target.cfHomeDir }),\n ...(target.command === undefined ? {} : { command: target.command }),\n redactor,\n };\n}\n\nfunction resolveApiEndpoint(target: Pick<CfLiveTraceTarget, \"apiEndpoint\" | \"region\">): string {\n if (target.apiEndpoint !== undefined && target.apiEndpoint.trim().length > 0) {\n return target.apiEndpoint.trim();\n }\n if (target.region === undefined) {\n throw new Error(\"CF region or apiEndpoint is required.\");\n }\n const endpoint = REGION_API_ENDPOINTS[target.region];\n if (endpoint === undefined) {\n throw new Error(`Unknown CF region: ${target.region}`);\n }\n return endpoint;\n}\n\nconst REGION_API_ENDPOINTS: Readonly<Record<string, string>> = {\n ae01: \"https://api.cf.ae01.hana.ondemand.com\",\n ap01: \"https://api.cf.ap01.hana.ondemand.com\",\n ap10: \"https://api.cf.ap10.hana.ondemand.com\",\n ap11: \"https://api.cf.ap11.hana.ondemand.com\",\n ap12: \"https://api.cf.ap12.hana.ondemand.com\",\n ap20: \"https://api.cf.ap20.hana.ondemand.com\",\n ap21: \"https://api.cf.ap21.hana.ondemand.com\",\n ap30: \"https://api.cf.ap30.hana.ondemand.com\",\n br10: \"https://api.cf.br10.hana.ondemand.com\",\n br20: \"https://api.cf.br20.hana.ondemand.com\",\n br30: \"https://api.cf.br30.hana.ondemand.com\",\n ca10: \"https://api.cf.ca10.hana.ondemand.com\",\n ca20: \"https://api.cf.ca20.hana.ondemand.com\",\n ch20: \"https://api.cf.ch20.hana.ondemand.com\",\n eu10: \"https://api.cf.eu10.hana.ondemand.com\",\n eu11: \"https://api.cf.eu11.hana.ondemand.com\",\n eu12: \"https://api.cf.eu12.hana.ondemand.com\",\n eu20: \"https://api.cf.eu20.hana.ondemand.com\",\n eu21: \"https://api.cf.eu21.hana.ondemand.com\",\n eu30: \"https://api.cf.eu30.hana.ondemand.com\",\n eu31: \"https://api.cf.eu31.hana.ondemand.com\",\n in30: \"https://api.cf.in30.hana.ondemand.com\",\n jp10: \"https://api.cf.jp10.hana.ondemand.com\",\n jp20: \"https://api.cf.jp20.hana.ondemand.com\",\n jp30: \"https://api.cf.jp30.hana.ondemand.com\",\n kr30: \"https://api.cf.kr30.hana.ondemand.com\",\n us10: \"https://api.cf.us10.hana.ondemand.com\",\n us11: \"https://api.cf.us11.hana.ondemand.com\",\n us20: \"https://api.cf.us20.hana.ondemand.com\",\n us21: \"https://api.cf.us21.hana.ondemand.com\",\n us30: \"https://api.cf.us30.hana.ondemand.com\",\n us31: \"https://api.cf.us31.hana.ondemand.com\",\n};\n\nfunction regionKeyForApiEndpoint(apiEndpoint: string): string | undefined {\n const normalized = normalizeApiEndpoint(apiEndpoint);\n for (const [key, endpoint] of Object.entries(REGION_API_ENDPOINTS)) {\n if (normalizeApiEndpoint(endpoint) === normalized) {\n return key;\n }\n }\n return undefined;\n}\n\nfunction normalizeApiEndpoint(apiEndpoint: string): string {\n return apiEndpoint.trim().replace(/\\/+$/, \"\").toLowerCase();\n}\n\nfunction parseSshStatus(stdout: string): \"enabled\" | \"disabled\" {\n return stdout.toLowerCase().includes(\"enabled\") && !stdout.toLowerCase().includes(\"disabled\") ? \"enabled\" : \"disabled\";\n}\n\nfunction buildPortForwardParams(\n target: InspectorTunnelTarget,\n localPort: number,\n): PortForwardParams {\n return {\n appName: resolveTunnelAppName(target),\n localPort,\n remoteHost: INSPECTOR_REMOTE_HOST,\n remotePort: INSPECTOR_REMOTE_PORT,\n keepAliveSeconds: TUNNEL_KEEPALIVE_SECONDS,\n ...(target.cfHomeDir === undefined ? {} : { cfHomeDir: target.cfHomeDir }),\n ...(target.command === undefined ? {} : { command: target.command }),\n ...(target.instanceIndex === undefined ? {} : { instanceIndex: target.instanceIndex }),\n };\n}\n\nfunction resolveTunnelAppName(target: InspectorTunnelTarget): string {\n const appName = target.appName ?? target.app;\n if (appName === undefined || appName.trim().length === 0) {\n throw new Error(\"CF app name is required for the inspector tunnel.\");\n }\n return appName;\n}\n\nasync function raceForwardReadiness(handle: PortForwardHandle, dependencies: TunnelDependencies): Promise<boolean> {\n const controller = new AbortController();\n let markFailed: () => void = () => {\n return;\n };\n const failedEarly = new Promise<false>((resolve) => {\n markFailed = (): void => {\n resolve(false);\n };\n handle.process.once(\"exit\", markFailed);\n handle.process.once(\"error\", markFailed);\n });\n const ready = dependencies.waitForLocalPort(handle.localPort, TUNNEL_READY_TIMEOUT_MS, controller.signal);\n try {\n return await Promise.race([ready, failedEarly]);\n } finally {\n controller.abort();\n handle.process.removeListener(\"exit\", markFailed);\n handle.process.removeListener(\"error\", markFailed);\n }\n}\n\nfunction resolveCommand(command?: string): { readonly bin: string; readonly argsPrefix: readonly string[] } {\n const resolvedBin = command ?? process.env[\"CF_LIVE_TRACE_CF_BIN\"] ?? \"cf\";\n return /\\.(?:c|m)?js$/i.test(resolvedBin)\n ? { bin: process.execPath, argsPrefix: [resolvedBin] }\n : { bin: resolvedBin, argsPrefix: [] };\n}\n\nfunction buildCfEnv(cfHomeDir?: string, envOverrides?: Record<string, string>): NodeJS.ProcessEnv {\n const env = { ...process.env };\n delete env[\"SAP_EMAIL\"];\n delete env[\"SAP_PASSWORD\"];\n if (cfHomeDir !== undefined && cfHomeDir.length > 0) {\n env[\"CF_HOME\"] = cfHomeDir;\n }\n return envOverrides === undefined ? env : { ...env, ...envOverrides };\n}\n\nfunction formatCfError(args: readonly string[], error: unknown, redactor?: (message: string) => string): string {\n const detail = extractErrorDetail(error);\n const message = `cf ${formatArgs(args)} failed${detail.length > 0 ? `: ${detail}` : \".\"}`;\n return redactor?.(message) ?? message;\n}\n\nfunction extractErrorDetail(error: unknown): string {\n if (!isRecord(error)) {\n return \"\";\n }\n const stderr = typeof error[\"stderr\"] === \"string\" ? error[\"stderr\"].trim() : \"\";\n if (stderr.length > 0) {\n return stderr;\n }\n return error[\"message\"] instanceof Error ? error[\"message\"].message : \"\";\n}\n\nfunction formatErrorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n\nfunction formatArgs(args: readonly string[]): string {\n return args.join(\" \");\n}\n\nfunction hasInspectorReadyMarker(stdout: string): boolean {\n return stdout.split(/\\r?\\n/).map((line) => line.trim()).includes(\"saptools-inspector-ready\");\n}\n\nfunction summarizeInspectorStartupOutput(stdout: string): string | undefined {\n const markers = stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"saptools-inspector-\"));\n return markers.length === 0 ? undefined : markers.join(\"; \");\n}\n\nfunction optionalDetail(detail: string | undefined): { readonly detail?: string } {\n return detail === undefined || detail.length === 0 ? {} : { detail };\n}\n\nfunction findFreePort(): Promise<number> {\n return new Promise<number>((resolve, reject) => {\n const server = createServer();\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n const port = typeof address === \"object\" && address !== null ? address.port : 0;\n server.close(() => {\n if (port === 0) {\n reject(new Error(\"Failed to allocate a local port.\"));\n return;\n }\n resolve(port);\n });\n });\n });\n}\n\nfunction waitForLocalPort(port: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n return new Promise<boolean>((resolve) => {\n let activeSocket: ReturnType<typeof netConnect> | undefined;\n let settled = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n const finish = (ready: boolean): void => {\n if (settled) {\n return;\n }\n settled = true;\n if (retryTimer !== undefined) {\n clearTimeout(retryTimer);\n }\n activeSocket?.destroy();\n activeSocket = undefined;\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(ready);\n };\n const onAbort = (): void => {\n finish(false);\n };\n const attempt = (): void => {\n if (settled) {\n return;\n }\n const socket = netConnect({ host: \"127.0.0.1\", port });\n activeSocket = socket;\n socket.once(\"connect\", () => {\n socket.destroy();\n activeSocket = undefined;\n finish(true);\n });\n socket.once(\"error\", () => {\n activeSocket = undefined;\n retryPortProbe(socket, deadline, attempt, finish, (timer) => {\n retryTimer = timer;\n });\n });\n };\n if (signal?.aborted === true) {\n finish(false);\n return;\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n attempt();\n });\n}\n\nfunction retryPortProbe(\n socket: ReturnType<typeof netConnect>,\n deadline: number,\n attempt: () => void,\n finish: (ready: boolean) => void,\n setRetryTimer: (timer: ReturnType<typeof setTimeout>) => void,\n): void {\n socket.destroy();\n if (Date.now() >= deadline) {\n finish(false);\n return;\n }\n setRetryTimer(setTimeout(attempt, TUNNEL_READY_POLL_MS));\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport interface CurrentCfTarget {\n readonly apiEndpoint: string;\n readonly regionKey?: string;\n readonly orgName: string;\n readonly spaceName: string;\n}\n\nexport interface CurrentCfTargetReadOptions {\n readonly command?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly timeoutMs?: number;\n}\n\nconst CURRENT_TARGET_TIMEOUT_MS = 30_000;\n\nexport async function readCurrentCfTarget(\n options?: CurrentCfTargetReadOptions,\n): Promise<CurrentCfTarget | undefined> {\n const opts = options ?? {};\n const command = resolveCommand(opts.command);\n const env = buildCfEnvForTarget(opts.env);\n try {\n const { stdout } = await execFileAsync(command.bin, [...command.argsPrefix, \"target\"], {\n env,\n maxBuffer: CF_MAX_BUFFER_BYTES,\n timeout: opts.timeoutMs ?? CURRENT_TARGET_TIMEOUT_MS,\n });\n return parseCurrentCfTarget(stdout);\n } catch {\n return undefined;\n }\n}\n\nexport function parseCurrentCfTarget(stdout: string): CurrentCfTarget | undefined {\n const fields = parseTargetFields(stdout);\n const apiEndpoint = fields.get(\"api endpoint\");\n const org = fields.get(\"org\");\n const space = fields.get(\"space\");\n if (!apiEndpoint || !org || !space) {\n return undefined;\n }\n const regionKey = regionKeyForApiEndpoint(apiEndpoint);\n return {\n apiEndpoint,\n ...(regionKey === undefined ? {} : { regionKey }),\n orgName: org,\n spaceName: space,\n };\n}\n\nfunction parseTargetFields(stdout: string): Map<string, string> {\n const map = new Map<string, string>();\n for (const line of stdout.split(/\\r?\\n/)) {\n const idx = line.indexOf(\":\");\n if (idx < 0) {\n continue;\n }\n const key = line.slice(0, idx).trim().toLowerCase();\n const val = line.slice(idx + 1).trim();\n if (key.length > 0 && val.length > 0) {\n map.set(key, val);\n }\n }\n return map;\n}\n\nfunction buildCfEnvForTarget(overrides?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const env = { ...process.env, ...overrides };\n delete env[\"SAP_EMAIL\"];\n delete env[\"SAP_PASSWORD\"];\n return env;\n}\n\nconst INSPECTOR_SIGNAL_COMMAND = [\n 'inspector_url=\"http://127.0.0.1:9229/json/list\"',\n 'inspector_ready() { ((command -v curl >/dev/null 2>&1 && curl -fsS --max-time 1 \"$inspector_url\" >/dev/null 2>&1) || (command -v wget >/dev/null 2>&1 && wget -qO- -T 1 \"$inspector_url\" >/dev/null 2>&1)); }',\n \"if inspector_ready; then\",\n \"echo saptools-inspector-ready\",\n \"exit 0\",\n \"fi\",\n 'node_pid=\"\"',\n \"best_score=-1\",\n \"for pid_dir in /proc/[0-9]*; do\",\n '[ -d \"$pid_dir\" ] || continue',\n 'node_exe=\"$(readlink \"$pid_dir/exe\" 2>/dev/null || true)\"',\n '[ \"${node_exe##*/}\" = \"node\" ] || continue',\n 'node_cmdline=\"$(tr \"\\\\000\" \" \" < \"$pid_dir/cmdline\" 2>/dev/null || true)\"',\n '[ -n \"$node_cmdline\" ] || continue',\n \"score=10\",\n 'if printf \"%s\\\\n\" \"$node_cmdline\" | grep -Eq \"@sap/cds|cds/bin/serve|serve\\\\.js|server\\\\.js|app\\\\.js|dist|build|index\\\\.js\"; then',\n \"score=20\",\n \"fi\",\n 'if [ \"$score\" -gt \"$best_score\" ]; then',\n 'best_score=\"$score\"',\n 'node_pid=\"${pid_dir##*/}\"',\n \"fi\",\n \"done\",\n 'if [ -z \"$node_pid\" ]; then',\n \"echo saptools-inspector-node-not-found\",\n \"exit 0\",\n \"fi\",\n 'echo \"saptools-inspector-node-pid=$node_pid\"',\n 'if kill -USR1 \"$node_pid\" 2>/dev/null; then',\n \"echo saptools-inspector-signaled\",\n \"else\",\n \"echo saptools-inspector-signal-failed\",\n \"exit 0\",\n \"fi\",\n \"attempt=0\",\n 'while [ \"$attempt\" -lt 20 ]; do',\n \"if inspector_ready; then\",\n \"echo saptools-inspector-ready\",\n \"exit 0\",\n \"fi\",\n \"attempt=$((attempt + 1))\",\n \"sleep 0.25\",\n \"done\",\n \"echo saptools-inspector-not-ready\",\n].join(\"\\\\n\");\n","import { connectInspector } from \"@saptools/cf-inspector\";\nimport type { InspectorSession } from \"@saptools/cf-inspector\";\n\nimport type { InspectorRuntimeClient } from \"./types.js\";\n\ninterface RuntimeEvaluateResult {\n readonly result?: { readonly value?: unknown };\n readonly exceptionDetails?: unknown;\n}\n\nexport async function connectRuntimeInspector(localPort: number): Promise<InspectorRuntimeClient> {\n const session = await connectInspector({ port: localPort, host: \"127.0.0.1\" });\n return new CdpRuntimeClient(session);\n}\n\nclass CdpRuntimeClient implements InspectorRuntimeClient {\n public constructor(private readonly session: InspectorSession) {}\n\n public async evaluate(expression: string, timeoutMs: number): Promise<unknown> {\n const result = await raceEvaluate(\n this.session.client.send<RuntimeEvaluateResult>(\"Runtime.evaluate\", {\n expression,\n awaitPromise: true,\n returnByValue: true,\n silent: true,\n }),\n timeoutMs,\n );\n return extractEvaluateValue(result);\n }\n\n public async close(): Promise<void> {\n await this.session.dispose();\n }\n}\n\nasync function raceEvaluate(promise: Promise<RuntimeEvaluateResult>, timeoutMs: number): Promise<RuntimeEvaluateResult> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(\"Runtime.evaluate timed out.\"));\n }, timeoutMs);\n });\n try {\n return await Promise.race([promise, timeout]);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n promise.catch(() => {\n return;\n });\n }\n}\n\nfunction extractEvaluateValue(result: RuntimeEvaluateResult): unknown {\n if (result.exceptionDetails !== undefined) {\n throw new Error(\"Runtime.evaluate failed.\");\n }\n return result.result?.value;\n}\n","import { ensureSshEnabled, openInspectorTunnel, prepareCfSession, startNodeInspector } from \"./cf.js\";\nimport { connectRuntimeInspector } from \"./inspector.js\";\nimport { parseDrainResult } from \"./payload.js\";\nimport { buildDrainExpression, buildInstallExpression, buildStopExpression } from \"./runtime-source.js\";\nimport { buildUrlSummaries } from \"./summary.js\";\nimport type {\n CfLiveTraceTarget,\n InspectorStartupResult,\n InspectorRuntimeClient,\n LiveTraceEvent,\n LiveTraceStartOptions,\n LiveTraceStateEvent,\n LiveTraceStopOptions,\n TunnelOpenResult,\n} from \"./types.js\";\n\nexport interface LiveTraceSessionOptions {\n readonly target: CfLiveTraceTarget;\n readonly onState?: (event: LiveTraceStateEvent) => void;\n readonly onEvents?: (events: readonly LiveTraceEvent[]) => void;\n readonly onSummary?: (summary: ReturnType<typeof buildUrlSummaries>) => void;\n readonly onLog?: (message: string) => void;\n}\n\nexport interface LiveTraceDependencies {\n prepareCfSession(target: CfLiveTraceTarget): Promise<void>;\n ensureSshEnabled(target: CfLiveTraceTarget): Promise<void>;\n tryStartNodeInspector(target: CfLiveTraceTarget): Promise<boolean | InspectorStartupResult>;\n openInspectorTunnel(target: CfLiveTraceTarget): Promise<TunnelOpenResult>;\n connectInspector(localPort: number): Promise<InspectorRuntimeClient>;\n setInterval(callback: () => void, ms: number): NodeJS.Timeout;\n clearInterval(handle: NodeJS.Timeout): void;\n}\n\nconst DRAIN_INTERVAL_MS = 250;\nconst DRAIN_BATCH_SIZE = 50;\nconst RUNTIME_QUEUE_SIZE = 1000;\nconst CONTROL_EVALUATE_TIMEOUT_MS = 5000;\nconst DRAIN_EVALUATE_TIMEOUT_MS = 10000;\nconst DRAIN_TIMEOUT_RETRY_LIMIT = 3;\nconst DRAIN_TRANSPORT_BODY_LIMIT = 20_000;\n\nconst defaultDependencies: LiveTraceDependencies = {\n prepareCfSession,\n ensureSshEnabled,\n tryStartNodeInspector: startNodeInspector,\n openInspectorTunnel,\n connectInspector: connectRuntimeInspector,\n setInterval,\n clearInterval,\n};\n\nexport class LiveTraceSession {\n private readonly dependencies: LiveTraceDependencies;\n private readonly events: LiveTraceEvent[] = [];\n private consecutiveDrainTimeouts = 0;\n private drainInFlight = false;\n private inspectorClient: InspectorRuntimeClient | undefined;\n private pollTimer: NodeJS.Timeout | undefined;\n private state: LiveTraceStateEvent[\"state\"] = \"idle\";\n private stopRequested = false;\n private tunnelHandle: { readonly localPort: number; readonly stop: () => void } | undefined;\n\n public constructor(\n private readonly options: LiveTraceSessionOptions,\n dependencies: Partial<LiveTraceDependencies> = {},\n ) {\n this.dependencies = { ...defaultDependencies, ...dependencies };\n }\n\n public async start(options: LiveTraceStartOptions = {}): Promise<void> {\n if (this.isRunning()) {\n return;\n }\n this.stopRequested = false;\n await this.startRuntimeTrace(resolveStartOptions(options));\n }\n\n public async stop(options: LiveTraceStopOptions): Promise<void> {\n this.stopRequested = true;\n if (!this.isRunning()) {\n this.postState(\"stopped\", `Trace stopped (${options.reason}).`, false, false);\n return;\n }\n const hadRuntimeHook = this.inspectorClient !== undefined;\n this.postState(\"stopping\", `Stopping trace (${options.reason}).`, hadRuntimeHook, hadRuntimeHook);\n const uninstalled = await this.stopRuntimeTrace(options.uninstallRuntimeHook);\n this.postState(\"stopped\", `Trace stopped (${options.reason}).`, false, hadRuntimeHook && !uninstalled);\n }\n\n public isRunning(): boolean {\n return [\"preparing\", \"enabling-ssh\", \"starting-inspector\", \"opening-tunnel\", \"injecting\", \"streaming\", \"stopping\"].includes(this.state);\n }\n\n private async startRuntimeTrace(options: Required<LiveTraceStartOptions>): Promise<void> {\n try {\n this.postState(\"preparing\", \"Preparing Cloud Foundry session.\", false, false);\n await this.dependencies.prepareCfSession(this.options.target);\n if (this.shouldStop()) {\n return;\n }\n await this.startInspector(options);\n } catch (error) {\n this.log(`Live Trace startup failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false);\n const startupError = toStartupError(error);\n if (!this.shouldStop()) {\n this.postState(\"error\", startupError.stateMessage, false, false);\n }\n throw startupError;\n }\n }\n\n private async startInspector(options: Required<LiveTraceStartOptions>): Promise<void> {\n this.postState(\"enabling-ssh\", \"Ensuring CF SSH access.\", false, false);\n await this.dependencies.ensureSshEnabled(this.options.target);\n if (this.shouldStop()) {\n return;\n }\n this.postState(\"starting-inspector\", \"Requesting Node Inspector startup.\", false, false);\n this.reportInspectorStartup(await this.dependencies.tryStartNodeInspector(this.options.target));\n if (this.shouldStop()) {\n return;\n }\n this.postState(\"opening-tunnel\", \"Opening Node Inspector tunnel.\", false, false);\n const tunnel = await this.dependencies.openInspectorTunnel(this.options.target);\n await this.attachInspector(tunnel, options);\n }\n\n private async attachInspector(tunnel: TunnelOpenResult, options: Required<LiveTraceStartOptions>): Promise<void> {\n if (this.shouldStop()) {\n stopLateTunnel(tunnel);\n return;\n }\n if (tunnel.status !== \"ready\") {\n throw new LiveTraceStartupError(\n \"Node Inspector is not reachable on 127.0.0.1:9229.\",\n \"Node Inspector is not reachable on 127.0.0.1:9229.\",\n );\n }\n this.tunnelHandle = tunnel.handle;\n this.inspectorClient = await this.dependencies.connectInspector(tunnel.handle.localPort);\n this.postState(\"injecting\", \"Installing runtime HTTP trace hook.\", false, false);\n await this.installRuntimeHook(options);\n this.startPolling(options.maxBodyBytes);\n this.postState(\"streaming\", \"Streaming runtime HTTP trace events.\", true, false);\n }\n\n private async installRuntimeHook(options: Required<LiveTraceStartOptions>): Promise<void> {\n await this.requireInspector().evaluate(buildInstallExpression({\n appId: this.options.target.app,\n instance: String(this.options.target.instanceIndex ?? 0),\n captureHeaders: options.captureHeaders,\n captureRequestBody: options.captureRequestBody,\n captureResponseBody: options.captureResponseBody,\n maxBodyBytes: options.maxBodyBytes,\n maxEvents: options.runtimeQueueSize,\n }), CONTROL_EVALUATE_TIMEOUT_MS);\n }\n\n private startPolling(maxBodyBytes: number): void {\n this.stopPolling();\n this.consecutiveDrainTimeouts = 0;\n this.pollTimer = this.dependencies.setInterval(() => {\n void this.drainTraceEvents(maxBodyBytes);\n }, DRAIN_INTERVAL_MS);\n }\n\n private async drainTraceEvents(maxBodyBytes: number): Promise<void> {\n if (this.drainInFlight || this.inspectorClient === undefined || this.state !== \"streaming\") {\n return;\n }\n this.drainInFlight = true;\n try {\n const payload = await this.inspectorClient.evaluate(\n buildDrainExpression(DRAIN_BATCH_SIZE, resolveDrainTransportBodyLimit(maxBodyBytes)),\n DRAIN_EVALUATE_TIMEOUT_MS,\n );\n this.consecutiveDrainTimeouts = 0;\n this.publishDrainedEvents(payload, maxBodyBytes);\n } catch (error) {\n await this.handleDrainFailure(error);\n } finally {\n this.drainInFlight = false;\n }\n }\n\n private publishDrainedEvents(payload: unknown, maxBodyBytes: number): void {\n const drained = parseDrainResult(payload, { appId: this.options.target.app, maxBodyBytes });\n if (drained.events.length === 0) {\n return;\n }\n this.events.push(...drained.events);\n this.events.splice(0, Math.max(0, this.events.length - RUNTIME_QUEUE_SIZE));\n this.options.onEvents?.(drained.events);\n this.options.onSummary?.(buildUrlSummaries(this.events));\n }\n\n private async handleDrainFailure(error: unknown): Promise<void> {\n if (isEvaluateTimeout(error)) {\n this.consecutiveDrainTimeouts += 1;\n if (this.consecutiveDrainTimeouts < DRAIN_TIMEOUT_RETRY_LIMIT) {\n this.log(`Live Trace drain timed out for ${this.options.target.app}; retrying (${String(this.consecutiveDrainTimeouts)}/${String(DRAIN_TIMEOUT_RETRY_LIMIT)}).`);\n return;\n }\n }\n this.log(`Live Trace stream failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false);\n this.postState(\"error\", \"Runtime HTTP trace connection was lost.\", false, true);\n }\n\n private async stopRuntimeTrace(uninstallRuntimeHook: boolean): Promise<boolean> {\n this.stopPolling();\n this.consecutiveDrainTimeouts = 0;\n const uninstalled = await this.stopInspectorHook(uninstallRuntimeHook);\n await this.closeInspectorClient();\n this.stopTunnel();\n return uninstalled;\n }\n\n private async closeInspectorClient(): Promise<void> {\n const client = this.inspectorClient;\n this.inspectorClient = undefined;\n try {\n await client?.close();\n } catch (error) {\n this.log(`Live Trace inspector close failed for ${this.options.target.app}: ${formatError(error)}`);\n }\n }\n\n private stopTunnel(): void {\n const tunnel = this.tunnelHandle;\n this.tunnelHandle = undefined;\n try {\n tunnel?.stop();\n } catch (error) {\n this.log(`Live Trace tunnel cleanup failed for ${this.options.target.app}: ${formatError(error)}`);\n }\n }\n\n private async stopInspectorHook(uninstallRuntimeHook: boolean): Promise<boolean> {\n if (this.inspectorClient === undefined) {\n return true;\n }\n try {\n await this.inspectorClient.evaluate(buildStopExpression({ uninstallRuntimeHook }), CONTROL_EVALUATE_TIMEOUT_MS);\n return uninstallRuntimeHook;\n } catch (error) {\n this.log(`Live Trace cleanup failed for ${this.options.target.app}: ${formatError(error)}`);\n return false;\n }\n }\n\n private stopPolling(): void {\n if (this.pollTimer === undefined) {\n return;\n }\n this.dependencies.clearInterval(this.pollTimer);\n this.pollTimer = undefined;\n }\n\n private postState(state: LiveTraceStateEvent[\"state\"], message: string, runtimeHookInstalled: boolean, runtimeHookMayRemain: boolean): void {\n this.state = state;\n this.options.onState?.({\n state,\n app: this.options.target.app,\n instance: String(this.options.target.instanceIndex ?? 0),\n message,\n runtimeHookInstalled,\n runtimeHookMayRemain,\n });\n }\n\n private requireInspector(): InspectorRuntimeClient {\n if (this.inspectorClient === undefined) {\n throw new Error(\"Inspector client is not connected.\");\n }\n return this.inspectorClient;\n }\n\n private shouldStop(): boolean {\n return this.stopRequested;\n }\n\n private log(message: string): void {\n this.options.onLog?.(message);\n }\n\n private reportInspectorStartup(result: boolean | InspectorStartupResult): void {\n const normalized = normalizeInspectorStartupResult(result);\n if (normalized.status === \"ready\") {\n return;\n }\n const detail = normalized.detail === undefined ? \"\" : `: ${normalized.detail}`;\n this.log(`Node Inspector startup was not confirmed for ${this.options.target.app}${detail}`);\n }\n}\n\nclass LiveTraceStartupError extends Error {\n public constructor(\n message: string,\n public readonly stateMessage: string,\n cause?: unknown,\n ) {\n super(message, cause === undefined ? undefined : { cause });\n }\n}\n\nfunction resolveStartOptions(options: LiveTraceStartOptions): Required<LiveTraceStartOptions> {\n return {\n captureHeaders: options.captureHeaders ?? true,\n captureRequestBody: options.captureRequestBody ?? true,\n captureResponseBody: options.captureResponseBody ?? true,\n maxBodyBytes: options.maxBodyBytes ?? 4096,\n runtimeQueueSize: options.runtimeQueueSize ?? RUNTIME_QUEUE_SIZE,\n };\n}\n\nfunction stopLateTunnel(tunnel: TunnelOpenResult): void {\n if (tunnel.status === \"ready\") {\n tunnel.handle.stop();\n }\n}\n\nfunction resolveDrainTransportBodyLimit(maxBodyBytes: number): number {\n return maxBodyBytes > 0 ? Math.min(maxBodyBytes, DRAIN_TRANSPORT_BODY_LIMIT) : DRAIN_TRANSPORT_BODY_LIMIT;\n}\n\nfunction isEvaluateTimeout(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(\"Runtime.evaluate timed out\");\n}\n\nfunction toStartupError(error: unknown): LiveTraceStartupError {\n if (error instanceof LiveTraceStartupError) {\n return error;\n }\n return new LiveTraceStartupError(\n \"Runtime HTTP trace could not be started.\",\n \"Runtime HTTP trace could not be started.\",\n error,\n );\n}\n\nfunction normalizeInspectorStartupResult(result: boolean | InspectorStartupResult): InspectorStartupResult {\n return typeof result === \"boolean\"\n ? { status: result ? \"ready\" : \"not-ready\" }\n : result;\n}\n\nfunction formatError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n"],"mappings":"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","names":["isRecord"]}
1
+ {"version":3,"sources":["../src/runtime-source.ts","../src/preview.ts","../src/payload.ts","../src/summary.ts","../src/cf.ts","../src/inspector.ts","../src/session.ts"],"sourcesContent":["export const CF_LIVE_TRACE_GLOBAL_NAME = \"__SAPTOOLS_CF_LIVE_TRACE__\";\nexport const CF_LIVE_TRACE_RUNTIME_VERSION = 2;\n\nexport interface RuntimeInstallOptions {\n readonly appId: string;\n readonly instance: string;\n readonly captureHeaders: boolean;\n readonly captureRequestBody: boolean;\n readonly captureResponseBody: boolean;\n readonly maxBodyBytes: number;\n readonly maxEvents: number;\n}\n\nexport interface StopExpressionOptions {\n readonly uninstallRuntimeHook: boolean;\n}\n\nexport const CF_LIVE_TRACE_RUNTIME_SOURCE = `\n(() => {\n const name = '${CF_LIVE_TRACE_GLOBAL_NAME}';\n const runtimeVersion = ${String(CF_LIVE_TRACE_RUNTIME_VERSION)};\n const existing = globalThis[name];\n if (existing && typeof existing.version === 'number' && existing.version >= runtimeVersion) return existing;\n if (existing && typeof existing.uninstall === 'function') {\n try {\n existing.uninstall();\n } catch {}\n }\n let BufferCtor = globalThis.Buffer;\n const state = {\n version: runtimeVersion,\n installed: false,\n enabled: false,\n options: { appId: '', instance: '0', captureHeaders: true, captureRequestBody: true, captureResponseBody: true, maxBodyBytes: 4096, maxEvents: 1000 },\n queue: [],\n droppedCount: 0,\n originals: {},\n seen: new WeakSet(),\n nextId: 1\n };\n const loadRequire = () => {\n if (typeof require === 'function') return require;\n if (globalThis.process && globalThis.process.mainModule && typeof globalThis.process.mainModule.require === 'function') {\n return globalThis.process.mainModule.require.bind(globalThis.process.mainModule);\n }\n return null;\n };\n const loadModule = async (moduleName) => {\n const requireFn = loadRequire();\n if (requireFn) return requireFn(moduleName);\n if (globalThis.process && typeof globalThis.process.getBuiltinModule === 'function') {\n return globalThis.process.getBuiltinModule(moduleName);\n }\n return await import('node:' + moduleName);\n };\n const toHeaderRecord = (headers) => {\n const output = {};\n if (!headers || !state.options.captureHeaders) return output;\n for (const key of Object.keys(headers)) {\n const value = headers[key];\n output[key] = Array.isArray(value) ? value.join(', ') : String(value);\n }\n return output;\n };\n const chunkText = (chunk) => {\n if (chunk === undefined || chunk === null) return '';\n if (BufferCtor && BufferCtor.isBuffer(chunk)) return chunk.toString('utf8');\n if (typeof chunk === 'string') return chunk;\n if (chunk instanceof Uint8Array && BufferCtor) return BufferCtor.from(chunk).toString('utf8');\n return '';\n };\n const byteLength = (text) => BufferCtor ? BufferCtor.byteLength(text) : text.length;\n const appendPreview = (current, chunk, enabled) => {\n if (!enabled) return current;\n const text = chunkText(chunk);\n if (state.options.maxBodyBytes <= 0) return current + text;\n if (current.length >= state.options.maxBodyBytes) return current;\n return (current + text).slice(0, state.options.maxBodyBytes);\n };\n const enqueue = (event) => {\n if (state.queue.length >= state.options.maxEvents) {\n state.queue.shift();\n state.droppedCount += 1;\n }\n state.queue.push(event);\n };\n const observe = (req, res) => {\n if (!state.enabled || !req || !res || state.seen.has(req)) return;\n state.seen.add(req);\n const started = Date.now();\n const initialUrl = String(req.url || '');\n const traceId = String(state.nextId++);\n let requestBytes = 0;\n let responseBytes = 0;\n let requestPreview = '';\n let responsePreview = '';\n let finished = false;\n const originalReqEmit = req.emit;\n const originalWrite = res.write;\n const originalEnd = res.end;\n req.emit = function patchedReqEmit(eventName, ...args) {\n if (eventName === 'data' && args[0] !== undefined) {\n const text = chunkText(args[0]);\n requestBytes += byteLength(text);\n requestPreview = appendPreview(requestPreview, args[0], state.options.captureRequestBody);\n }\n return originalReqEmit.apply(this, [eventName, ...args]);\n };\n res.write = function patchedWrite(chunk, ...args) {\n const text = chunkText(chunk);\n responseBytes += byteLength(text);\n responsePreview = appendPreview(responsePreview, chunk, state.options.captureResponseBody);\n return originalWrite.apply(this, [chunk, ...args]);\n };\n res.end = function patchedEnd(chunk, ...args) {\n if (chunk !== undefined) {\n const text = chunkText(chunk);\n responseBytes += byteLength(text);\n responsePreview = appendPreview(responsePreview, chunk, state.options.captureResponseBody);\n }\n return originalEnd.apply(this, [chunk, ...args]);\n };\n const finish = () => {\n if (finished) return;\n finished = true;\n req.emit = originalReqEmit;\n res.write = originalWrite;\n res.end = originalEnd;\n const rawUrl = initialUrl || String(req.url || '');\n enqueue({\n id: traceId,\n timestamp: new Date().toISOString(),\n instance: state.options.instance,\n method: String(req.method || 'GET').toUpperCase(),\n path: rawUrl.split('?')[0] || rawUrl,\n url: rawUrl,\n normalizedUrl: rawUrl,\n status: typeof res.statusCode === 'number' ? res.statusCode : null,\n durationMs: Date.now() - started,\n requestBytes,\n responseBytes,\n requestHeaders: toHeaderRecord(req.headers),\n responseHeaders: toHeaderRecord(typeof res.getHeaders === 'function' ? res.getHeaders() : {}),\n requestBodyPreview: requestPreview,\n responseBodyPreview: responsePreview,\n requestBodyTruncated: state.options.maxBodyBytes > 0 && requestPreview.length >= state.options.maxBodyBytes,\n responseBodyTruncated: state.options.maxBodyBytes > 0 && responsePreview.length >= state.options.maxBodyBytes,\n droppedBeforeEvent: state.droppedCount,\n traceId,\n correlationId: req.headers && typeof req.headers['x-saptools-trace-id'] === 'string' ? req.headers['x-saptools-trace-id'] : null\n });\n };\n res.once('finish', finish);\n res.once('close', finish);\n };\n const patchEmit = (serverPrototype) => {\n if (!serverPrototype || serverPrototype.emit.__saptoolsCfLiveTracePatched) return undefined;\n const original = serverPrototype.emit;\n const patched = function patchedServerEmit(eventName, ...args) {\n if (eventName === 'request') observe(args[0], args[1]);\n return original.apply(this, [eventName, ...args]);\n };\n patched.__saptoolsCfLiveTracePatched = true;\n serverPrototype.emit = patched;\n return original;\n };\n const toTransportLimit = (value) => {\n const numeric = Number(value);\n return Number.isFinite(numeric) && numeric > 0 ? Math.floor(numeric) : 0;\n };\n const limitPreview = (event, previewKey, truncatedKey, maxChars) => {\n const preview = event[previewKey];\n if (maxChars <= 0 || typeof preview !== 'string' || preview.length <= maxChars) return event;\n return { ...event, [previewKey]: preview.slice(0, maxChars), [truncatedKey]: true };\n };\n const eventForDrain = (event, maxChars) => {\n if (!event || typeof event !== 'object') return event;\n let output = { ...event };\n output = limitPreview(output, 'requestBodyPreview', 'requestBodyTruncated', maxChars);\n output = limitPreview(output, 'responseBodyPreview', 'responseBodyTruncated', maxChars);\n return output;\n };\n const api = {\n version: runtimeVersion,\n async install(options) {\n state.options = { ...state.options, ...options };\n if (!state.installed) {\n if (!BufferCtor) {\n const bufferModule = await loadModule('buffer');\n BufferCtor = bufferModule && bufferModule.Buffer ? bufferModule.Buffer : BufferCtor;\n }\n const http = await loadModule('http');\n const https = await loadModule('https');\n state.originals.httpServerEmit = patchEmit(http && http.Server && http.Server.prototype);\n state.originals.httpsServerEmit = patchEmit(https && https.Server && https.Server.prototype);\n state.installed = true;\n }\n state.enabled = true;\n return api.status();\n },\n disable() {\n state.enabled = false;\n return api.status();\n },\n drainEvents(maxCount, maxTransportBodyBytes) {\n const count = Math.max(0, Math.min(Number(maxCount) || 0, state.queue.length));\n const transportLimit = toTransportLimit(maxTransportBodyBytes);\n const events = state.queue.splice(0, count).map((event) => eventForDrain(event, transportLimit));\n return { events, droppedCount: state.droppedCount, queueSize: state.queue.length };\n },\n status() {\n return { installed: state.installed, enabled: state.enabled, queueSize: state.queue.length, droppedCount: state.droppedCount, maxEvents: state.options.maxEvents };\n },\n async uninstall() {\n state.enabled = false;\n const http = await loadModule('http');\n const https = await loadModule('https');\n if (state.originals.httpServerEmit && http && http.Server) http.Server.prototype.emit = state.originals.httpServerEmit;\n if (state.originals.httpsServerEmit && https && https.Server) https.Server.prototype.emit = state.originals.httpsServerEmit;\n state.installed = false;\n return api.status();\n }\n };\n globalThis[name] = api;\n return api;\n})()\n`;\n\nexport function buildInstallExpression(options: RuntimeInstallOptions): string {\n return `${CF_LIVE_TRACE_RUNTIME_SOURCE}.install(${JSON.stringify(options)})`;\n}\n\nexport function buildDrainExpression(maxCount: number, maxTransportBodyBytes: number): string {\n return `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.drainEvents(${String(maxCount)}, ${String(maxTransportBodyBytes)}) ?? { events: [], droppedCount: 0, queueSize: 0 }`;\n}\n\nexport function buildStopExpression(options: StopExpressionOptions): string {\n return options.uninstallRuntimeHook\n ? `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.uninstall() ?? { installed: false, enabled: false }`\n : `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.disable() ?? { installed: false, enabled: false }`;\n}\n","export interface PreviewTruncationResult {\n readonly preview: string;\n readonly truncated: boolean;\n}\n\nexport function truncatePreview(preview: string, maxChars: number): PreviewTruncationResult {\n if (maxChars <= 0) {\n return { preview, truncated: false };\n }\n if (preview.length <= maxChars) {\n return { preview, truncated: false };\n }\n return { preview: preview.slice(0, maxChars), truncated: true };\n}\n","import { truncatePreview } from \"./preview.js\";\nimport type { DrainParseResult, LiveTraceEvent } from \"./types.js\";\n\nexport interface DrainParseOptions {\n readonly appId: string;\n readonly maxBodyBytes: number;\n}\n\nlet fallbackEventId = 0;\n\nexport function parseDrainResult(payload: unknown, options: DrainParseOptions): DrainParseResult {\n if (!isRecord(payload)) {\n return { events: [], droppedCount: 0, queueSize: 0 };\n }\n const rawEvents = Array.isArray(payload[\"events\"]) ? payload[\"events\"] : [];\n return {\n events: rawEvents\n .map((event) => parseRuntimeEvent(event, options))\n .filter((event): event is LiveTraceEvent => event !== null),\n droppedCount: readNonNegativeNumber(payload[\"droppedCount\"]),\n queueSize: readNonNegativeNumber(payload[\"queueSize\"]),\n };\n}\n\nfunction parseRuntimeEvent(payload: unknown, options: DrainParseOptions): LiveTraceEvent | null {\n if (!isRecord(payload)) {\n return null;\n }\n const rawUrl = readString(payload[\"url\"]) ?? readString(payload[\"normalizedUrl\"]) ?? readString(payload[\"path\"]);\n if (rawUrl === null) {\n return null;\n }\n const requestBody = limitBodyPreview(readString(payload[\"requestBodyPreview\"]) ?? \"\", options.maxBodyBytes);\n const responseBody = limitBodyPreview(readString(payload[\"responseBodyPreview\"]) ?? \"\", options.maxBodyBytes);\n return buildEvent(payload, rawUrl, requestBody, responseBody, options);\n}\n\nfunction buildEvent(\n payload: Record<string, unknown>,\n rawUrl: string,\n requestBody: { readonly preview: string; readonly truncated: boolean },\n responseBody: { readonly preview: string; readonly truncated: boolean },\n options: DrainParseOptions,\n): LiveTraceEvent {\n return {\n id: readString(payload[\"id\"]) ?? nextFallbackEventId(),\n timestamp: readString(payload[\"timestamp\"]) ?? new Date().toISOString(),\n appId: options.appId,\n instance: readString(payload[\"instance\"]) ?? \"0\",\n method: (readString(payload[\"method\"]) ?? \"GET\").toUpperCase(),\n path: readString(payload[\"path\"]) ?? normalizePath(rawUrl),\n url: rawUrl,\n normalizedUrl: readString(payload[\"normalizedUrl\"]) ?? normalizePath(rawUrl),\n status: readNullableNumber(payload[\"status\"]),\n durationMs: readNullableNumber(payload[\"durationMs\"]),\n requestBytes: readNonNegativeNumber(payload[\"requestBytes\"]),\n responseBytes: readNonNegativeNumber(payload[\"responseBytes\"]),\n requestHeaders: readHeaders(payload[\"requestHeaders\"]),\n responseHeaders: readHeaders(payload[\"responseHeaders\"]),\n requestBodyPreview: requestBody.preview,\n responseBodyPreview: responseBody.preview,\n requestBodyTruncated: payload[\"requestBodyTruncated\"] === true || requestBody.truncated,\n responseBodyTruncated: payload[\"responseBodyTruncated\"] === true || responseBody.truncated,\n droppedBeforeEvent: readNonNegativeNumber(payload[\"droppedBeforeEvent\"]),\n source: \"runtime-http\",\n traceId: readString(payload[\"traceId\"]) ?? readString(payload[\"id\"]) ?? \"\",\n correlationId: readString(payload[\"correlationId\"]),\n };\n}\n\nfunction readHeaders(value: unknown): Record<string, string> {\n if (!isRecord(value)) {\n return {};\n }\n const headers: Record<string, string> = {};\n for (const [key, rawValue] of Object.entries(value)) {\n const header = readHeaderValue(rawValue);\n if (header !== null) {\n headers[key] = header;\n }\n }\n return headers;\n}\n\nfunction readHeaderValue(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item)).join(\", \");\n }\n return null;\n}\n\nfunction limitBodyPreview(preview: string, maxChars: number): { readonly preview: string; readonly truncated: boolean } {\n return truncatePreview(preview, maxChars);\n}\n\nfunction normalizePath(rawUrl: string): string {\n try {\n const parsed = new URL(rawUrl, \"https://saptools.local\");\n return `${parsed.pathname}${parsed.search}`;\n } catch {\n return rawUrl;\n }\n}\n\nfunction readString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction readNullableNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction readNonNegativeNumber(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? value : 0;\n}\n\nfunction nextFallbackEventId(): string {\n fallbackEventId += 1;\n return `runtime-${String(fallbackEventId)}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { LiveTraceEvent, LiveTraceUrlSummary } from \"./types.js\";\n\ntype StatusBucket = \"2xx\" | \"3xx\" | \"4xx\" | \"5xx\" | \"unknown\";\n\ninterface MutableSummary {\n readonly normalizedUrl: string;\n readonly displayUrl: string;\n readonly methods: Set<string>;\n totalCount: number;\n readonly statusCounts: Record<StatusBucket, number>;\n latestStatus: number | null;\n latestDurationMs: number | null;\n latestSeenAt: string;\n}\n\nexport function buildUrlSummaries(events: readonly LiveTraceEvent[]): LiveTraceUrlSummary[] {\n const summaries = new Map<string, MutableSummary>();\n for (const event of events) {\n const normalizedUrl = normalizeEventUrl(event);\n const current = summaries.get(normalizedUrl) ?? createSummary(normalizedUrl);\n updateSummary(current, event);\n summaries.set(normalizedUrl, current);\n }\n return [...summaries.values()]\n .map(toImmutableSummary)\n .sort((left, right) => right.latestSeenAt.localeCompare(left.latestSeenAt));\n}\n\nexport function normalizeEventUrl(event: LiveTraceEvent): string {\n const candidate = event.normalizedUrl.length > 0 ? event.normalizedUrl : event.url.length > 0 ? event.url : event.path;\n return normalizeUrl(candidate);\n}\n\nfunction updateSummary(summary: MutableSummary, event: LiveTraceEvent): void {\n summary.methods.add(event.method);\n summary.totalCount += 1;\n summary.statusCounts[toStatusBucket(event.status)] += 1;\n if (event.timestamp >= summary.latestSeenAt) {\n summary.latestStatus = event.status;\n summary.latestDurationMs = event.durationMs;\n summary.latestSeenAt = event.timestamp;\n }\n}\n\nfunction normalizeUrl(rawUrl: string): string {\n if (rawUrl.trim().length === 0) {\n return rawUrl;\n }\n try {\n const parsed = new URL(rawUrl, \"https://saptools.local\");\n return `${parsed.pathname}${parsed.search}`;\n } catch {\n return rawUrl;\n }\n}\n\nfunction createSummary(normalizedUrl: string): MutableSummary {\n return {\n normalizedUrl,\n displayUrl: normalizedUrl,\n methods: new Set<string>(),\n totalCount: 0,\n statusCounts: { \"2xx\": 0, \"3xx\": 0, \"4xx\": 0, \"5xx\": 0, unknown: 0 },\n latestStatus: null,\n latestDurationMs: null,\n latestSeenAt: \"\",\n };\n}\n\nfunction toImmutableSummary(summary: MutableSummary): LiveTraceUrlSummary {\n return {\n normalizedUrl: summary.normalizedUrl,\n displayUrl: summary.displayUrl,\n methods: [...summary.methods].sort(),\n totalCount: summary.totalCount,\n statusCounts: { ...summary.statusCounts },\n latestStatus: summary.latestStatus,\n latestDurationMs: summary.latestDurationMs,\n latestSeenAt: summary.latestSeenAt,\n };\n}\n\nfunction toStatusBucket(status: number | null): StatusBucket {\n if (status === null) {\n return \"unknown\";\n }\n if (status >= 200 && status < 300) {\n return \"2xx\";\n }\n if (status >= 300 && status < 400) {\n return \"3xx\";\n }\n if (status >= 400 && status < 500) {\n return \"4xx\";\n }\n if (status >= 500 && status < 600) {\n return \"5xx\";\n }\n return \"unknown\";\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { connect as netConnect, createServer } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nimport type { CfLiveTraceTarget, InspectorStartupResult, PortForwardHandle, TunnelOpenResult } from \"./types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CF_MAX_BUFFER_BYTES = 8 * 1024 * 1024;\nconst CF_COMMAND_TIMEOUT_MS = 180_000;\nconst CF_SSH_READY_TIMEOUT_MS = 60_000;\nconst INSPECTOR_SIGNAL_TIMEOUT_MS = 15_000;\nconst INSPECTOR_REMOTE_HOST = \"127.0.0.1\";\nconst INSPECTOR_REMOTE_PORT = 9229;\nconst TUNNEL_KEEPALIVE_SECONDS = 6 * 60 * 60;\nconst TUNNEL_READY_TIMEOUT_MS = 20_000;\nconst TUNNEL_READY_POLL_MS = 200;\n\nexport interface RunCfOptions {\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly envOverrides?: Record<string, string>;\n readonly timeoutMs?: number;\n readonly redactor?: (message: string) => string;\n}\n\nexport interface CfDependencies {\n runCf(args: readonly string[], options: RunCfOptions): Promise<string>;\n}\n\nexport interface TunnelDependencies {\n allocatePort(): Promise<number>;\n spawnPortForward(params: PortForwardParams): PortForwardHandle;\n waitForLocalPort(port: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean>;\n}\n\nexport interface PortForwardParams {\n readonly appName: string;\n readonly localPort: number;\n readonly remoteHost: string;\n readonly remotePort: number;\n readonly keepAliveSeconds: number;\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly instanceIndex?: number;\n}\n\nexport interface InspectorTunnelTarget {\n readonly app?: string;\n readonly appName?: string;\n readonly cfHomeDir?: string;\n readonly command?: string;\n readonly instanceIndex?: number;\n}\n\nexport async function createTemporaryCfHome(): Promise<string> {\n return await mkdtemp(join(tmpdir(), \"saptools-cf-live-trace-\"));\n}\n\nexport async function removeTemporaryCfHome(cfHomeDir: string): Promise<void> {\n await rm(cfHomeDir, { recursive: true, force: true });\n}\n\nexport async function prepareCfSession(\n target: CfLiveTraceTarget,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<void> {\n const apiEndpoint = resolveApiEndpoint(target);\n const redactor = createSecretRedactor([target.email, target.password]);\n const baseOptions = buildRunOptions(target, redactor);\n await dependencies.runCf([\"api\", apiEndpoint], baseOptions);\n await dependencies.runCf([\"auth\"], {\n ...baseOptions,\n envOverrides: { CF_USERNAME: target.email, CF_PASSWORD: target.password },\n });\n await dependencies.runCf([\"target\", \"-o\", target.org, \"-s\", target.space], baseOptions);\n}\n\nexport async function ensureSshEnabled(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<void> {\n const redactor = createSecretRedactor([target.email, target.password]);\n const options = buildRunOptions(target, redactor);\n const status = await dependencies.runCf([\"ssh-enabled\", target.app], options);\n if (parseSshStatus(status) === \"enabled\") {\n return;\n }\n await dependencies.runCf([\"enable-ssh\", target.app], options);\n await dependencies.runCf([\"restart\", target.app], options);\n await dependencies.runCf(buildCfSshArgs(target.app, target.instanceIndex, [\"-c\", \"true\"]), {\n ...options,\n timeoutMs: CF_SSH_READY_TIMEOUT_MS,\n });\n}\n\nexport async function tryStartNodeInspector(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<boolean> {\n const result = await startNodeInspector(target, dependencies);\n return result.status === \"ready\";\n}\n\nexport async function startNodeInspector(\n target: Pick<CfLiveTraceTarget, \"app\" | \"cfHomeDir\" | \"command\" | \"email\" | \"password\" | \"instanceIndex\">,\n dependencies: CfDependencies = defaultCfDependencies,\n): Promise<InspectorStartupResult> {\n const redactor = createSecretRedactor([target.email, target.password]);\n try {\n const stdout = await dependencies.runCf(\n buildCfSshArgs(target.app, target.instanceIndex, [\"-c\", buildInspectorSignalCommand()]),\n { ...buildRunOptions(target, redactor), timeoutMs: INSPECTOR_SIGNAL_TIMEOUT_MS },\n );\n return hasInspectorReadyMarker(stdout)\n ? { status: \"ready\" }\n : { status: \"not-ready\", ...optionalDetail(summarizeInspectorStartupOutput(stdout)) };\n } catch (error) {\n return { status: \"not-ready\", ...optionalDetail(redactor(formatErrorMessage(error))) };\n }\n}\n\nexport async function openInspectorTunnel(\n target: InspectorTunnelTarget,\n dependencies: TunnelDependencies = defaultTunnelDependencies,\n): Promise<TunnelOpenResult> {\n const localPort = await dependencies.allocatePort();\n const handle = dependencies.spawnPortForward(buildPortForwardParams(target, localPort));\n const ready = await raceForwardReadiness(handle, dependencies);\n if (!ready) {\n handle.stop();\n return { status: \"not-reachable\" };\n }\n return { status: \"ready\", handle };\n}\n\nexport function buildCfSshArgs(appName: string, instanceIndex: number | undefined, tail: readonly string[]): string[] {\n const args = [\"ssh\", appName];\n if (instanceIndex !== undefined) {\n args.push(\"-i\", String(instanceIndex));\n }\n return [...args, ...tail];\n}\n\nexport function buildInspectorSignalCommand(): string {\n return INSPECTOR_SIGNAL_COMMAND;\n}\n\nexport function createSecretRedactor(secrets: readonly string[]): (message: string) => string {\n const values = secrets.map((secret) => secret.trim()).filter((secret) => secret.length > 0);\n return (message: string): string => values.reduce((current, secret) => current.split(secret).join(\"<redacted>\"), message);\n}\n\nexport async function runCfCommand(args: readonly string[], options: RunCfOptions): Promise<string> {\n const command = resolveCommand(options.command);\n try {\n const { stdout } = await execFileAsync(command.bin, [...command.argsPrefix, ...args], {\n env: buildCfEnv(options.cfHomeDir, options.envOverrides),\n maxBuffer: CF_MAX_BUFFER_BYTES,\n timeout: options.timeoutMs ?? CF_COMMAND_TIMEOUT_MS,\n });\n return stdout;\n } catch (error) {\n throw new Error(formatCfError(args, error, options.redactor), { cause: error });\n }\n}\n\nexport function spawnPortForward(params: PortForwardParams): PortForwardHandle {\n const command = resolveCommand(params.command);\n const forwardSpec = `${String(params.localPort)}:${params.remoteHost}:${String(params.remotePort)}`;\n const sshArgs = buildCfSshArgs(params.appName, params.instanceIndex, [\"-L\", forwardSpec, \"-c\", `sleep ${String(params.keepAliveSeconds)}`]);\n const child = spawn(command.bin, [...command.argsPrefix, ...sshArgs], {\n env: buildCfEnv(params.cfHomeDir),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n child.stdout.resume();\n child.stderr.resume();\n return {\n process: child,\n localPort: params.localPort,\n stop(): void {\n if (!child.killed) {\n child.kill();\n }\n },\n };\n}\n\nexport const defaultCfDependencies: CfDependencies = {\n runCf: runCfCommand,\n};\n\nexport const defaultTunnelDependencies: TunnelDependencies = {\n allocatePort: findFreePort,\n spawnPortForward,\n waitForLocalPort,\n};\n\nfunction buildRunOptions(target: Pick<CfLiveTraceTarget, \"cfHomeDir\" | \"command\">, redactor: (message: string) => string): RunCfOptions {\n return {\n ...(target.cfHomeDir === undefined ? {} : { cfHomeDir: target.cfHomeDir }),\n ...(target.command === undefined ? {} : { command: target.command }),\n redactor,\n };\n}\n\nfunction resolveApiEndpoint(target: Pick<CfLiveTraceTarget, \"apiEndpoint\" | \"region\">): string {\n if (target.apiEndpoint !== undefined && target.apiEndpoint.trim().length > 0) {\n return target.apiEndpoint.trim();\n }\n if (target.region === undefined) {\n throw new Error(\"CF region or apiEndpoint is required.\");\n }\n const endpoint = REGION_API_ENDPOINTS[target.region];\n if (endpoint === undefined) {\n throw new Error(`Unknown CF region: ${target.region}`);\n }\n return endpoint;\n}\n\nconst REGION_API_ENDPOINTS: Readonly<Record<string, string>> = {\n ae01: \"https://api.cf.ae01.hana.ondemand.com\",\n ap01: \"https://api.cf.ap01.hana.ondemand.com\",\n ap10: \"https://api.cf.ap10.hana.ondemand.com\",\n ap11: \"https://api.cf.ap11.hana.ondemand.com\",\n ap12: \"https://api.cf.ap12.hana.ondemand.com\",\n ap20: \"https://api.cf.ap20.hana.ondemand.com\",\n ap21: \"https://api.cf.ap21.hana.ondemand.com\",\n ap30: \"https://api.cf.ap30.hana.ondemand.com\",\n br10: \"https://api.cf.br10.hana.ondemand.com\",\n br20: \"https://api.cf.br20.hana.ondemand.com\",\n br30: \"https://api.cf.br30.hana.ondemand.com\",\n ca10: \"https://api.cf.ca10.hana.ondemand.com\",\n ca20: \"https://api.cf.ca20.hana.ondemand.com\",\n ch20: \"https://api.cf.ch20.hana.ondemand.com\",\n eu10: \"https://api.cf.eu10.hana.ondemand.com\",\n eu11: \"https://api.cf.eu11.hana.ondemand.com\",\n eu12: \"https://api.cf.eu12.hana.ondemand.com\",\n eu20: \"https://api.cf.eu20.hana.ondemand.com\",\n eu21: \"https://api.cf.eu21.hana.ondemand.com\",\n eu30: \"https://api.cf.eu30.hana.ondemand.com\",\n eu31: \"https://api.cf.eu31.hana.ondemand.com\",\n in30: \"https://api.cf.in30.hana.ondemand.com\",\n jp10: \"https://api.cf.jp10.hana.ondemand.com\",\n jp20: \"https://api.cf.jp20.hana.ondemand.com\",\n jp30: \"https://api.cf.jp30.hana.ondemand.com\",\n kr30: \"https://api.cf.kr30.hana.ondemand.com\",\n us10: \"https://api.cf.us10.hana.ondemand.com\",\n us11: \"https://api.cf.us11.hana.ondemand.com\",\n us20: \"https://api.cf.us20.hana.ondemand.com\",\n us21: \"https://api.cf.us21.hana.ondemand.com\",\n us30: \"https://api.cf.us30.hana.ondemand.com\",\n us31: \"https://api.cf.us31.hana.ondemand.com\",\n};\n\nfunction regionKeyForApiEndpoint(apiEndpoint: string): string | undefined {\n const normalized = normalizeApiEndpoint(apiEndpoint);\n for (const [key, endpoint] of Object.entries(REGION_API_ENDPOINTS)) {\n if (normalizeApiEndpoint(endpoint) === normalized) {\n return key;\n }\n }\n return undefined;\n}\n\nfunction normalizeApiEndpoint(apiEndpoint: string): string {\n return apiEndpoint.trim().replace(/\\/+$/, \"\").toLowerCase();\n}\n\nfunction parseSshStatus(stdout: string): \"enabled\" | \"disabled\" {\n return stdout.toLowerCase().includes(\"enabled\") && !stdout.toLowerCase().includes(\"disabled\") ? \"enabled\" : \"disabled\";\n}\n\nfunction buildPortForwardParams(\n target: InspectorTunnelTarget,\n localPort: number,\n): PortForwardParams {\n return {\n appName: resolveTunnelAppName(target),\n localPort,\n remoteHost: INSPECTOR_REMOTE_HOST,\n remotePort: INSPECTOR_REMOTE_PORT,\n keepAliveSeconds: TUNNEL_KEEPALIVE_SECONDS,\n ...(target.cfHomeDir === undefined ? {} : { cfHomeDir: target.cfHomeDir }),\n ...(target.command === undefined ? {} : { command: target.command }),\n ...(target.instanceIndex === undefined ? {} : { instanceIndex: target.instanceIndex }),\n };\n}\n\nfunction resolveTunnelAppName(target: InspectorTunnelTarget): string {\n const appName = target.appName ?? target.app;\n if (appName === undefined || appName.trim().length === 0) {\n throw new Error(\"CF app name is required for the inspector tunnel.\");\n }\n return appName;\n}\n\nasync function raceForwardReadiness(handle: PortForwardHandle, dependencies: TunnelDependencies): Promise<boolean> {\n const controller = new AbortController();\n let markFailed: () => void = () => {\n return;\n };\n const failedEarly = new Promise<false>((resolve) => {\n markFailed = (): void => {\n resolve(false);\n };\n handle.process.once(\"exit\", markFailed);\n handle.process.once(\"error\", markFailed);\n });\n const ready = dependencies.waitForLocalPort(handle.localPort, TUNNEL_READY_TIMEOUT_MS, controller.signal);\n try {\n return await Promise.race([ready, failedEarly]);\n } finally {\n controller.abort();\n handle.process.removeListener(\"exit\", markFailed);\n handle.process.removeListener(\"error\", markFailed);\n }\n}\n\nfunction resolveCommand(command?: string): { readonly bin: string; readonly argsPrefix: readonly string[] } {\n const resolvedBin = command ?? process.env[\"CF_LIVE_TRACE_CF_BIN\"] ?? \"cf\";\n return /\\.(?:c|m)?js$/i.test(resolvedBin)\n ? { bin: process.execPath, argsPrefix: [resolvedBin] }\n : { bin: resolvedBin, argsPrefix: [] };\n}\n\nfunction buildCfEnv(cfHomeDir?: string, envOverrides?: Record<string, string>): NodeJS.ProcessEnv {\n const env = { ...process.env };\n delete env[\"SAP_EMAIL\"];\n delete env[\"SAP_PASSWORD\"];\n if (cfHomeDir !== undefined && cfHomeDir.length > 0) {\n env[\"CF_HOME\"] = cfHomeDir;\n }\n return envOverrides === undefined ? env : { ...env, ...envOverrides };\n}\n\nfunction formatCfError(args: readonly string[], error: unknown, redactor?: (message: string) => string): string {\n const detail = extractErrorDetail(error);\n const message = `cf ${formatArgs(args)} failed${detail.length > 0 ? `: ${detail}` : \".\"}`;\n return redactor?.(message) ?? message;\n}\n\nfunction extractErrorDetail(error: unknown): string {\n if (!isRecord(error)) {\n return \"\";\n }\n const stderr = typeof error[\"stderr\"] === \"string\" ? error[\"stderr\"].trim() : \"\";\n if (stderr.length > 0) {\n return stderr;\n }\n const message = error[\"message\"];\n if (typeof message === \"string\") {\n return message.trim();\n }\n return message instanceof Error ? message.message.trim() : \"\";\n}\n\nfunction formatErrorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n\nfunction formatArgs(args: readonly string[]): string {\n return args.join(\" \");\n}\n\nfunction hasInspectorReadyMarker(stdout: string): boolean {\n return stdout.split(/\\r?\\n/).map((line) => line.trim()).includes(\"saptools-inspector-ready\");\n}\n\nfunction summarizeInspectorStartupOutput(stdout: string): string | undefined {\n const markers = stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"saptools-inspector-\"));\n return markers.length === 0 ? undefined : markers.join(\"; \");\n}\n\nfunction optionalDetail(detail: string | undefined): { readonly detail?: string } {\n return detail === undefined || detail.length === 0 ? {} : { detail };\n}\n\nfunction findFreePort(): Promise<number> {\n return new Promise<number>((resolve, reject) => {\n const server = createServer();\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n const port = typeof address === \"object\" && address !== null ? address.port : 0;\n server.close(() => {\n if (port === 0) {\n reject(new Error(\"Failed to allocate a local port.\"));\n return;\n }\n resolve(port);\n });\n });\n });\n}\n\nfunction waitForLocalPort(port: number, timeoutMs: number, signal?: AbortSignal): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n return new Promise<boolean>((resolve) => {\n let activeSocket: ReturnType<typeof netConnect> | undefined;\n let settled = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n const finish = (ready: boolean): void => {\n if (settled) {\n return;\n }\n settled = true;\n if (retryTimer !== undefined) {\n clearTimeout(retryTimer);\n }\n activeSocket?.destroy();\n activeSocket = undefined;\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(ready);\n };\n const onAbort = (): void => {\n finish(false);\n };\n const attempt = (): void => {\n if (settled) {\n return;\n }\n const socket = netConnect({ host: \"127.0.0.1\", port });\n activeSocket = socket;\n socket.once(\"connect\", () => {\n socket.destroy();\n activeSocket = undefined;\n finish(true);\n });\n socket.once(\"error\", () => {\n activeSocket = undefined;\n retryPortProbe(socket, deadline, attempt, finish, (timer) => {\n retryTimer = timer;\n });\n });\n };\n if (signal?.aborted === true) {\n finish(false);\n return;\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n attempt();\n });\n}\n\nfunction retryPortProbe(\n socket: ReturnType<typeof netConnect>,\n deadline: number,\n attempt: () => void,\n finish: (ready: boolean) => void,\n setRetryTimer: (timer: ReturnType<typeof setTimeout>) => void,\n): void {\n socket.destroy();\n if (Date.now() >= deadline) {\n finish(false);\n return;\n }\n setRetryTimer(setTimeout(attempt, TUNNEL_READY_POLL_MS));\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport interface CurrentCfTarget {\n readonly apiEndpoint: string;\n readonly regionKey?: string;\n readonly orgName: string;\n readonly spaceName: string;\n}\n\nexport interface CurrentCfTargetReadOptions {\n readonly command?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly timeoutMs?: number;\n}\n\nconst CURRENT_TARGET_TIMEOUT_MS = 30_000;\n\nexport async function readCurrentCfTarget(\n options?: CurrentCfTargetReadOptions,\n): Promise<CurrentCfTarget | undefined> {\n const opts = options ?? {};\n const command = resolveCommand(opts.command);\n const env = buildCfEnvForTarget(opts.env);\n try {\n const { stdout } = await execFileAsync(command.bin, [...command.argsPrefix, \"target\"], {\n env,\n maxBuffer: CF_MAX_BUFFER_BYTES,\n timeout: opts.timeoutMs ?? CURRENT_TARGET_TIMEOUT_MS,\n });\n return parseCurrentCfTarget(stdout);\n } catch {\n return undefined;\n }\n}\n\nexport function parseCurrentCfTarget(stdout: string): CurrentCfTarget | undefined {\n const fields = parseTargetFields(stdout);\n const apiEndpoint = fields.get(\"api endpoint\");\n const org = fields.get(\"org\");\n const space = fields.get(\"space\");\n if (!apiEndpoint || !org || !space) {\n return undefined;\n }\n const regionKey = regionKeyForApiEndpoint(apiEndpoint);\n return {\n apiEndpoint,\n ...(regionKey === undefined ? {} : { regionKey }),\n orgName: org,\n spaceName: space,\n };\n}\n\nfunction parseTargetFields(stdout: string): Map<string, string> {\n const map = new Map<string, string>();\n for (const line of stdout.split(/\\r?\\n/)) {\n const idx = line.indexOf(\":\");\n if (idx < 0) {\n continue;\n }\n const key = line.slice(0, idx).trim().toLowerCase();\n const val = line.slice(idx + 1).trim();\n if (key.length > 0 && val.length > 0) {\n map.set(key, val);\n }\n }\n return map;\n}\n\nfunction buildCfEnvForTarget(overrides?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const env = { ...process.env, ...overrides };\n delete env[\"SAP_EMAIL\"];\n delete env[\"SAP_PASSWORD\"];\n return env;\n}\n\nconst INSPECTOR_SIGNAL_COMMAND = [\n 'inspector_url=\"http://127.0.0.1:9229/json/list\"',\n 'inspector_ready() { ((command -v curl >/dev/null 2>&1 && curl -fsS --max-time 1 \"$inspector_url\" >/dev/null 2>&1) || (command -v wget >/dev/null 2>&1 && wget -qO- -T 1 \"$inspector_url\" >/dev/null 2>&1)); }',\n \"if inspector_ready; then\",\n \"echo saptools-inspector-ready\",\n \"exit 0\",\n \"fi\",\n 'node_pid=\"\"',\n \"best_score=-1\",\n \"for pid_dir in /proc/[0-9]*; do\",\n '[ -d \"$pid_dir\" ] || continue',\n 'node_exe=\"$(readlink \"$pid_dir/exe\" 2>/dev/null || true)\"',\n '[ \"${node_exe##*/}\" = \"node\" ] || continue',\n 'node_cmdline=\"$(tr \"\\\\000\" \" \" < \"$pid_dir/cmdline\" 2>/dev/null || true)\"',\n '[ -n \"$node_cmdline\" ] || continue',\n \"score=10\",\n 'if printf \"%s\\\\n\" \"$node_cmdline\" | grep -Eq \"@sap/cds|cds/bin/serve|serve\\\\.js|server\\\\.js|app\\\\.js|dist|build|index\\\\.js\"; then',\n \"score=20\",\n \"fi\",\n 'if [ \"$score\" -gt \"$best_score\" ]; then',\n 'best_score=\"$score\"',\n 'node_pid=\"${pid_dir##*/}\"',\n \"fi\",\n \"done\",\n 'if [ -z \"$node_pid\" ]; then',\n \"echo saptools-inspector-node-not-found\",\n \"exit 0\",\n \"fi\",\n 'echo \"saptools-inspector-node-pid=$node_pid\"',\n 'if kill -USR1 \"$node_pid\" 2>/dev/null; then',\n \"echo saptools-inspector-signaled\",\n \"else\",\n \"echo saptools-inspector-signal-failed\",\n \"exit 0\",\n \"fi\",\n \"attempt=0\",\n 'while [ \"$attempt\" -lt 20 ]; do',\n \"if inspector_ready; then\",\n \"echo saptools-inspector-ready\",\n \"exit 0\",\n \"fi\",\n \"attempt=$((attempt + 1))\",\n \"sleep 0.25\",\n \"done\",\n \"echo saptools-inspector-not-ready\",\n].join(\"\\\\n\");\n","import { connectInspector } from \"@saptools/cf-inspector\";\nimport type { InspectorSession } from \"@saptools/cf-inspector\";\n\nimport type { InspectorRuntimeClient } from \"./types.js\";\n\ninterface RuntimeEvaluateResult {\n readonly result?: { readonly value?: unknown };\n readonly exceptionDetails?: unknown;\n}\n\nexport async function connectRuntimeInspector(localPort: number): Promise<InspectorRuntimeClient> {\n const session = await connectInspector({ port: localPort, host: \"127.0.0.1\" });\n return new CdpRuntimeClient(session);\n}\n\nclass CdpRuntimeClient implements InspectorRuntimeClient {\n public constructor(private readonly session: InspectorSession) {}\n\n public async evaluate(expression: string, timeoutMs: number): Promise<unknown> {\n const result = await raceEvaluate(\n this.session.client.send<RuntimeEvaluateResult>(\"Runtime.evaluate\", {\n expression,\n awaitPromise: true,\n returnByValue: true,\n silent: true,\n }),\n timeoutMs,\n );\n return extractEvaluateValue(result);\n }\n\n public async close(): Promise<void> {\n await this.session.dispose();\n }\n}\n\nasync function raceEvaluate(promise: Promise<RuntimeEvaluateResult>, timeoutMs: number): Promise<RuntimeEvaluateResult> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(\"Runtime.evaluate timed out.\"));\n }, timeoutMs);\n });\n try {\n return await Promise.race([promise, timeout]);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n promise.catch(() => {\n return;\n });\n }\n}\n\nfunction extractEvaluateValue(result: RuntimeEvaluateResult): unknown {\n if (result.exceptionDetails !== undefined) {\n throw new Error(\"Runtime.evaluate failed.\");\n }\n return result.result?.value;\n}\n","import { ensureSshEnabled, openInspectorTunnel, prepareCfSession, startNodeInspector } from \"./cf.js\";\nimport { connectRuntimeInspector } from \"./inspector.js\";\nimport { parseDrainResult } from \"./payload.js\";\nimport { buildDrainExpression, buildInstallExpression, buildStopExpression } from \"./runtime-source.js\";\nimport { buildUrlSummaries } from \"./summary.js\";\nimport type {\n CfLiveTraceTarget,\n InspectorStartupResult,\n InspectorRuntimeClient,\n LiveTraceEvent,\n LiveTraceStartOptions,\n LiveTraceStateEvent,\n LiveTraceStopOptions,\n TunnelOpenResult,\n} from \"./types.js\";\n\nexport interface LiveTraceSessionOptions {\n readonly target: CfLiveTraceTarget;\n readonly onState?: (event: LiveTraceStateEvent) => void;\n readonly onEvents?: (events: readonly LiveTraceEvent[]) => void;\n readonly onSummary?: (summary: ReturnType<typeof buildUrlSummaries>) => void;\n readonly onLog?: (message: string) => void;\n}\n\nexport interface LiveTraceDependencies {\n prepareCfSession(target: CfLiveTraceTarget): Promise<void>;\n ensureSshEnabled(target: CfLiveTraceTarget): Promise<void>;\n tryStartNodeInspector(target: CfLiveTraceTarget): Promise<boolean | InspectorStartupResult>;\n openInspectorTunnel(target: CfLiveTraceTarget): Promise<TunnelOpenResult>;\n connectInspector(localPort: number): Promise<InspectorRuntimeClient>;\n setInterval(callback: () => void, ms: number): NodeJS.Timeout;\n clearInterval(handle: NodeJS.Timeout): void;\n}\n\nconst DRAIN_INTERVAL_MS = 250;\nconst DRAIN_BATCH_SIZE = 50;\nconst RUNTIME_QUEUE_SIZE = 1000;\nconst CONTROL_EVALUATE_TIMEOUT_MS = 5000;\nconst DRAIN_EVALUATE_TIMEOUT_MS = 10000;\nconst DRAIN_TIMEOUT_RETRY_LIMIT = 3;\nconst DRAIN_TRANSPORT_BODY_LIMIT = 20_000;\n\nconst defaultDependencies: LiveTraceDependencies = {\n prepareCfSession,\n ensureSshEnabled,\n tryStartNodeInspector: startNodeInspector,\n openInspectorTunnel,\n connectInspector: connectRuntimeInspector,\n setInterval,\n clearInterval,\n};\n\nexport class LiveTraceSession {\n private readonly dependencies: LiveTraceDependencies;\n private readonly events: LiveTraceEvent[] = [];\n private consecutiveDrainTimeouts = 0;\n private drainInFlight = false;\n private inspectorClient: InspectorRuntimeClient | undefined;\n private pollTimer: NodeJS.Timeout | undefined;\n private state: LiveTraceStateEvent[\"state\"] = \"idle\";\n private stopRequested = false;\n private tunnelHandle: { readonly localPort: number; readonly stop: () => void } | undefined;\n\n public constructor(\n private readonly options: LiveTraceSessionOptions,\n dependencies: Partial<LiveTraceDependencies> = {},\n ) {\n this.dependencies = { ...defaultDependencies, ...dependencies };\n }\n\n public async start(options: LiveTraceStartOptions = {}): Promise<void> {\n if (this.isRunning()) {\n return;\n }\n this.stopRequested = false;\n await this.startRuntimeTrace(resolveStartOptions(options));\n }\n\n public async stop(options: LiveTraceStopOptions): Promise<void> {\n this.stopRequested = true;\n if (!this.isRunning()) {\n if (this.state === \"error\" && options.reason === \"error\") {\n return;\n }\n this.postState(\"stopped\", `Trace stopped (${options.reason}).`, false, false);\n return;\n }\n const hadRuntimeHook = this.inspectorClient !== undefined;\n this.postState(\"stopping\", `Stopping trace (${options.reason}).`, hadRuntimeHook, hadRuntimeHook);\n const uninstalled = await this.stopRuntimeTrace(options.uninstallRuntimeHook);\n this.postState(\"stopped\", `Trace stopped (${options.reason}).`, false, hadRuntimeHook && !uninstalled);\n }\n\n public isRunning(): boolean {\n return [\"preparing\", \"enabling-ssh\", \"starting-inspector\", \"opening-tunnel\", \"injecting\", \"streaming\", \"stopping\"].includes(this.state);\n }\n\n private async startRuntimeTrace(options: Required<LiveTraceStartOptions>): Promise<void> {\n try {\n this.postState(\"preparing\", \"Preparing Cloud Foundry session.\", false, false);\n await this.dependencies.prepareCfSession(this.options.target);\n if (this.shouldStop()) {\n return;\n }\n await this.startInspector(options);\n } catch (error) {\n this.log(`Live Trace startup failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false);\n const startupError = toStartupError(error);\n if (!this.shouldStop()) {\n this.postState(\"error\", startupError.stateMessage, false, false);\n }\n throw startupError;\n }\n }\n\n private async startInspector(options: Required<LiveTraceStartOptions>): Promise<void> {\n this.postState(\"enabling-ssh\", \"Ensuring CF SSH access.\", false, false);\n await this.dependencies.ensureSshEnabled(this.options.target);\n if (this.shouldStop()) {\n return;\n }\n this.postState(\"starting-inspector\", \"Requesting Node Inspector startup.\", false, false);\n this.reportInspectorStartup(await this.dependencies.tryStartNodeInspector(this.options.target));\n if (this.shouldStop()) {\n return;\n }\n this.postState(\"opening-tunnel\", \"Opening Node Inspector tunnel.\", false, false);\n const tunnel = await this.dependencies.openInspectorTunnel(this.options.target);\n await this.attachInspector(tunnel, options);\n }\n\n private async attachInspector(tunnel: TunnelOpenResult, options: Required<LiveTraceStartOptions>): Promise<void> {\n if (this.shouldStop()) {\n stopLateTunnel(tunnel);\n return;\n }\n if (tunnel.status !== \"ready\") {\n throw new LiveTraceStartupError(\n \"Node Inspector is not reachable on 127.0.0.1:9229.\",\n \"Node Inspector is not reachable on 127.0.0.1:9229.\",\n );\n }\n this.tunnelHandle = tunnel.handle;\n this.inspectorClient = await this.dependencies.connectInspector(tunnel.handle.localPort);\n this.postState(\"injecting\", \"Installing runtime HTTP trace hook.\", false, false);\n await this.installRuntimeHook(options);\n this.startPolling(options.maxBodyBytes);\n this.postState(\"streaming\", \"Streaming runtime HTTP trace events.\", true, false);\n }\n\n private async installRuntimeHook(options: Required<LiveTraceStartOptions>): Promise<void> {\n await this.requireInspector().evaluate(buildInstallExpression({\n appId: this.options.target.app,\n instance: String(this.options.target.instanceIndex ?? 0),\n captureHeaders: options.captureHeaders,\n captureRequestBody: options.captureRequestBody,\n captureResponseBody: options.captureResponseBody,\n maxBodyBytes: options.maxBodyBytes,\n maxEvents: options.runtimeQueueSize,\n }), CONTROL_EVALUATE_TIMEOUT_MS);\n }\n\n private startPolling(maxBodyBytes: number): void {\n this.stopPolling();\n this.consecutiveDrainTimeouts = 0;\n this.pollTimer = this.dependencies.setInterval(() => {\n void this.drainTraceEvents(maxBodyBytes);\n }, DRAIN_INTERVAL_MS);\n }\n\n private async drainTraceEvents(maxBodyBytes: number): Promise<void> {\n if (this.drainInFlight || this.inspectorClient === undefined || this.state !== \"streaming\") {\n return;\n }\n this.drainInFlight = true;\n try {\n const payload = await this.inspectorClient.evaluate(\n buildDrainExpression(DRAIN_BATCH_SIZE, resolveDrainTransportBodyLimit(maxBodyBytes)),\n DRAIN_EVALUATE_TIMEOUT_MS,\n );\n this.consecutiveDrainTimeouts = 0;\n this.publishDrainedEvents(payload, maxBodyBytes);\n } catch (error) {\n await this.handleDrainFailure(error);\n } finally {\n this.drainInFlight = false;\n }\n }\n\n private publishDrainedEvents(payload: unknown, maxBodyBytes: number): void {\n const drained = parseDrainResult(payload, { appId: this.options.target.app, maxBodyBytes });\n if (drained.events.length === 0) {\n return;\n }\n this.events.push(...drained.events);\n this.events.splice(0, Math.max(0, this.events.length - RUNTIME_QUEUE_SIZE));\n this.options.onEvents?.(drained.events);\n this.options.onSummary?.(buildUrlSummaries(this.events));\n }\n\n private async handleDrainFailure(error: unknown): Promise<void> {\n if (isEvaluateTimeout(error)) {\n this.consecutiveDrainTimeouts += 1;\n if (this.consecutiveDrainTimeouts < DRAIN_TIMEOUT_RETRY_LIMIT) {\n this.log(`Live Trace drain timed out for ${this.options.target.app}; retrying (${String(this.consecutiveDrainTimeouts)}/${String(DRAIN_TIMEOUT_RETRY_LIMIT)}).`);\n return;\n }\n }\n this.log(`Live Trace stream failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false);\n this.postState(\"error\", \"Runtime HTTP trace connection was lost.\", false, true);\n }\n\n private async stopRuntimeTrace(uninstallRuntimeHook: boolean): Promise<boolean> {\n this.stopPolling();\n this.consecutiveDrainTimeouts = 0;\n const uninstalled = await this.stopInspectorHook(uninstallRuntimeHook);\n await this.closeInspectorClient();\n this.stopTunnel();\n return uninstalled;\n }\n\n private async closeInspectorClient(): Promise<void> {\n const client = this.inspectorClient;\n this.inspectorClient = undefined;\n try {\n await client?.close();\n } catch (error) {\n this.log(`Live Trace inspector close failed for ${this.options.target.app}: ${formatError(error)}`);\n }\n }\n\n private stopTunnel(): void {\n const tunnel = this.tunnelHandle;\n this.tunnelHandle = undefined;\n try {\n tunnel?.stop();\n } catch (error) {\n this.log(`Live Trace tunnel cleanup failed for ${this.options.target.app}: ${formatError(error)}`);\n }\n }\n\n private async stopInspectorHook(uninstallRuntimeHook: boolean): Promise<boolean> {\n if (this.inspectorClient === undefined) {\n return true;\n }\n try {\n await this.inspectorClient.evaluate(buildStopExpression({ uninstallRuntimeHook }), CONTROL_EVALUATE_TIMEOUT_MS);\n return uninstallRuntimeHook;\n } catch (error) {\n this.log(`Live Trace cleanup failed for ${this.options.target.app}: ${formatError(error)}`);\n return false;\n }\n }\n\n private stopPolling(): void {\n if (this.pollTimer === undefined) {\n return;\n }\n this.dependencies.clearInterval(this.pollTimer);\n this.pollTimer = undefined;\n }\n\n private postState(state: LiveTraceStateEvent[\"state\"], message: string, runtimeHookInstalled: boolean, runtimeHookMayRemain: boolean): void {\n this.state = state;\n this.options.onState?.({\n state,\n app: this.options.target.app,\n instance: String(this.options.target.instanceIndex ?? 0),\n message,\n runtimeHookInstalled,\n runtimeHookMayRemain,\n });\n }\n\n private requireInspector(): InspectorRuntimeClient {\n if (this.inspectorClient === undefined) {\n throw new Error(\"Inspector client is not connected.\");\n }\n return this.inspectorClient;\n }\n\n private shouldStop(): boolean {\n return this.stopRequested;\n }\n\n private log(message: string): void {\n this.options.onLog?.(message);\n }\n\n private reportInspectorStartup(result: boolean | InspectorStartupResult): void {\n const normalized = normalizeInspectorStartupResult(result);\n if (normalized.status === \"ready\") {\n return;\n }\n const detail = normalized.detail === undefined ? \"\" : `: ${normalized.detail}`;\n this.log(`Node Inspector startup was not confirmed for ${this.options.target.app}${detail}`);\n }\n}\n\nclass LiveTraceStartupError extends Error {\n public constructor(\n message: string,\n public readonly stateMessage: string,\n cause?: unknown,\n ) {\n super(message, cause === undefined ? undefined : { cause });\n }\n}\n\nfunction resolveStartOptions(options: LiveTraceStartOptions): Required<LiveTraceStartOptions> {\n return {\n captureHeaders: options.captureHeaders ?? true,\n captureRequestBody: options.captureRequestBody ?? true,\n captureResponseBody: options.captureResponseBody ?? true,\n maxBodyBytes: options.maxBodyBytes ?? 4096,\n runtimeQueueSize: options.runtimeQueueSize ?? RUNTIME_QUEUE_SIZE,\n };\n}\n\nfunction stopLateTunnel(tunnel: TunnelOpenResult): void {\n if (tunnel.status === \"ready\") {\n tunnel.handle.stop();\n }\n}\n\nfunction resolveDrainTransportBodyLimit(maxBodyBytes: number): number {\n return maxBodyBytes > 0 ? Math.min(maxBodyBytes, DRAIN_TRANSPORT_BODY_LIMIT) : DRAIN_TRANSPORT_BODY_LIMIT;\n}\n\nfunction isEvaluateTimeout(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(\"Runtime.evaluate timed out\");\n}\n\nfunction toStartupError(error: unknown): LiveTraceStartupError {\n if (error instanceof LiveTraceStartupError) {\n return error;\n }\n return new LiveTraceStartupError(\n \"Runtime HTTP trace could not be started.\",\n \"Runtime HTTP trace could not be started.\",\n error,\n );\n}\n\nfunction normalizeInspectorStartupResult(result: boolean | InspectorStartupResult): InspectorStartupResult {\n return typeof result === \"boolean\"\n ? { status: result ? \"ready\" : \"not-ready\" }\n : result;\n}\n\nfunction formatError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim().length > 0 ? message.trim() : \"Unknown error\";\n}\n"],"mappings":"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","names":["isRecord"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saptools/cf-live-trace",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Inject a runtime HTTP trace hook into SAP BTP Cloud Foundry Node.js apps and stream request/response events from the CLI.",
5
5
  "type": "module",
6
6
  "publishConfig": {