@saptools/cf-live-trace 0.1.9 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/cli.js +193 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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/trace-compact.ts","../src/trace-inspect.ts","../src/trace-store.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 = 3;\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 let staleCleanup = null;\n if (existing && typeof existing.uninstall === 'function') {\n try {\n const cleanup = existing.uninstall();\n if (cleanup && typeof cleanup.then === 'function') {\n staleCleanup = Promise.resolve(cleanup).catch(() => undefined);\n }\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 nextDrainId: 1,\n pendingDrain: null\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 chunkBuffer = (chunk) => {\n if (!BufferCtor || chunk === undefined || chunk === null) return null;\n if (BufferCtor.isBuffer(chunk)) return chunk;\n if (typeof chunk === 'string' || chunk instanceof Uint8Array) return BufferCtor.from(chunk);\n return null;\n };\n const textByteLength = (text) => BufferCtor ? BufferCtor.byteLength(text) : text.length;\n const chunkByteLength = (chunk) => {\n if (chunk === undefined || chunk === null) return 0;\n if (BufferCtor && BufferCtor.isBuffer(chunk)) return chunk.length;\n if (chunk instanceof Uint8Array) return chunk.byteLength;\n return textByteLength(typeof chunk === 'string' ? chunk : '');\n };\n const truncateTextToBytes = (text, maxBytes) => {\n if (!BufferCtor) return text.slice(0, maxBytes);\n const encoded = BufferCtor.from(text);\n if (encoded.length <= maxBytes) return text;\n let boundary = Math.min(maxBytes, encoded.length);\n while (boundary > 0 && encoded[boundary] !== undefined && (encoded[boundary] & 0xc0) === 0x80) {\n boundary -= 1;\n }\n return encoded.subarray(0, boundary).toString('utf8');\n };\n const appendPreview = (chunks, currentBytes, chunk, enabled) => {\n if (!enabled) return currentBytes;\n const maxBytes = Math.floor(Number(state.options.maxBodyBytes) || 0);\n if (maxBytes <= 0) return currentBytes;\n const remaining = maxBytes - currentBytes;\n if (remaining <= 0) return currentBytes;\n const buffer = chunkBuffer(chunk);\n if (buffer) {\n const addition = buffer.subarray(0, remaining);\n chunks.push(addition);\n return currentBytes + addition.length;\n }\n const text = chunkText(chunk);\n const addition = truncateTextToBytes(text, remaining);\n chunks.push(addition);\n return currentBytes + textByteLength(addition);\n };\n const completeUtf8Length = (buffer) => {\n if (!buffer || buffer.length === 0) return 0;\n let start = buffer.length - 1;\n while (start > 0 && (buffer[start] & 0xc0) === 0x80) start -= 1;\n const lead = buffer[start];\n const expected = lead <= 0x7f ? 1 : lead <= 0xdf ? 2 : lead <= 0xef ? 3 : lead <= 0xf7 ? 4 : 1;\n return buffer.length - start < expected ? start : buffer.length;\n };\n const previewText = (chunks, retainedBytes) => {\n if (!BufferCtor) {\n const text = chunks.join('');\n return { text, bytes: textByteLength(text) };\n }\n const buffer = BufferCtor.concat(chunks, retainedBytes);\n const completeBytes = completeUtf8Length(buffer);\n return { text: buffer.subarray(0, completeBytes).toString('utf8'), bytes: completeBytes };\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 const requestPreviewChunks = [];\n const responsePreviewChunks = [];\n let requestPreviewBytes = 0;\n let responsePreviewBytes = 0;\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 requestBytes += chunkByteLength(args[0]);\n requestPreviewBytes = appendPreview(requestPreviewChunks, requestPreviewBytes, args[0], state.options.captureRequestBody);\n }\n return originalReqEmit.apply(this, [eventName, ...args]);\n };\n res.write = function patchedWrite(chunk, ...args) {\n responseBytes += chunkByteLength(chunk);\n responsePreviewBytes = appendPreview(responsePreviewChunks, responsePreviewBytes, chunk, state.options.captureResponseBody);\n return originalWrite.apply(this, [chunk, ...args]);\n };\n res.end = function patchedEnd(chunk, ...args) {\n if (chunk !== undefined) {\n responseBytes += chunkByteLength(chunk);\n responsePreviewBytes = appendPreview(responsePreviewChunks, responsePreviewBytes, 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 const requestPreview = previewText(requestPreviewChunks, requestPreviewBytes);\n const responsePreview = previewText(responsePreviewChunks, responsePreviewBytes);\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.text,\n responseBodyPreview: responsePreview.text,\n requestBodyTruncated: state.options.captureRequestBody && state.options.maxBodyBytes > 0 && requestBytes > requestPreview.bytes,\n responseBodyTruncated: state.options.captureResponseBody && state.options.maxBodyBytes > 0 && responseBytes > responsePreview.bytes,\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, maxBytes) => {\n const preview = event[previewKey];\n if (maxBytes <= 0 || typeof preview !== 'string' || textByteLength(preview) <= maxBytes) return event;\n return { ...event, [previewKey]: truncateTextToBytes(preview, maxBytes), [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 acknowledgeDrain = (drainId) => {\n const pending = state.pendingDrain;\n if (!pending || drainId !== pending.id) return;\n const drainedEvents = new Set(pending.sourceEvents);\n state.queue = state.queue.filter((event) => !drainedEvents.has(event));\n state.pendingDrain = null;\n };\n const drainResult = () => {\n const pending = state.pendingDrain;\n if (!pending) {\n return { drainId: null, events: [], droppedCount: state.droppedCount, queueSize: state.queue.length };\n }\n return {\n drainId: pending.id,\n events: pending.events,\n droppedCount: state.droppedCount,\n queueSize: state.queue.length\n };\n };\n const api = {\n version: runtimeVersion,\n async install(options) {\n if (staleCleanup) {\n await staleCleanup;\n staleCleanup = null;\n }\n state.options = {\n ...state.options,\n ...options,\n maxBodyBytes: toTransportLimit(options && options.maxBodyBytes),\n maxEvents: Math.max(1, Math.floor(Number(options && options.maxEvents) || 1))\n };\n state.queue = [];\n state.pendingDrain = null;\n state.droppedCount = 0;\n state.seen = new WeakSet();\n state.nextId = 1;\n state.nextDrainId = 1;\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, acknowledgedDrainId) {\n acknowledgeDrain(acknowledgedDrainId);\n if (state.pendingDrain) return drainResult();\n const count = Math.max(0, Math.min(Number(maxCount) || 0, state.queue.length));\n const transportLimit = toTransportLimit(maxTransportBodyBytes);\n if (count === 0) return drainResult();\n const sourceEvents = state.queue.slice(0, count);\n state.pendingDrain = {\n id: 'd' + String(state.nextDrainId++),\n sourceEvents,\n events: sourceEvents.map((event) => eventForDrain(event, transportLimit))\n };\n return drainResult();\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 state.queue = [];\n state.pendingDrain = null;\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(\n maxCount: number,\n maxTransportBodyBytes: number,\n acknowledgedDrainId: string | null = null,\n): string {\n const acknowledgement = JSON.stringify(acknowledgedDrainId);\n return `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.drainEvents(${String(maxCount)}, ${String(maxTransportBodyBytes)}, ${acknowledgement}) ?? { drainId: null, 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 { Buffer } from \"node:buffer\";\n\nexport interface PreviewTruncationResult {\n readonly preview: string;\n readonly truncated: boolean;\n}\n\nexport function truncatePreview(preview: string, maxBytes: number): PreviewTruncationResult {\n if (maxBytes <= 0) {\n return { preview, truncated: false };\n }\n const encoded = Buffer.from(preview);\n if (encoded.length <= maxBytes) {\n return { preview, truncated: false };\n }\n return {\n preview: encoded.subarray(0, utf8Boundary(encoded, maxBytes)).toString(\"utf8\"),\n truncated: true,\n };\n}\n\nfunction utf8Boundary(encoded: Buffer, maxBytes: number): number {\n let boundary = Math.min(maxBytes, encoded.length);\n while (boundary > 0 && isContinuationByte(encoded[boundary])) {\n boundary -= 1;\n }\n return boundary;\n}\n\nfunction isContinuationByte(value: number | undefined): boolean {\n return value !== undefined && (value & 0xc0) === 0x80;\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 { drainId: null, events: [], droppedCount: 0, queueSize: 0 };\n }\n const rawEvents = Array.isArray(payload[\"events\"]) ? payload[\"events\"] : [];\n return {\n drainId: readDrainId(payload[\"drainId\"]),\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 readDrainId(value: unknown): string | null {\n return typeof value === \"string\" && /^d\\d+$/.test(value) ? value : null;\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 type { StoredTraceEvent } from \"./trace-store.js\";\n\nexport type TraceBodyFormat = \"empty\" | \"json\" | \"xml\" | \"html\" | \"form\" | \"text\" | \"binary\" | \"unknown\";\n\nexport interface CompactTraceEvent {\n readonly id: string;\n readonly sessionId: string;\n readonly requestId: string;\n readonly timestamp: string;\n readonly instance: string;\n readonly method: string;\n readonly path: string;\n readonly url: string;\n readonly normalizedUrl: string;\n readonly status: number | null;\n readonly durationMs: number | null;\n readonly requestBytes: number;\n readonly responseBytes: number;\n readonly requestBodyFormat: TraceBodyFormat;\n readonly responseBodyFormat: TraceBodyFormat;\n readonly requestBodyPreview: string;\n readonly requestBodyPreviewRemainingChars: number;\n readonly responseBodyPreview: string;\n readonly responseBodyPreviewRemainingChars: number;\n readonly requestBodyTruncated: boolean;\n readonly responseBodyTruncated: boolean;\n readonly droppedBeforeEvent: number;\n readonly source: \"runtime-http\";\n readonly traceId: string;\n readonly correlationId: string | null;\n}\n\nconst COMPACT_BODY_PREVIEW_CHARS = 128;\nconst SENSITIVE_QUERY_KEYS = new Set([\n \"access_token\",\n \"api_key\",\n \"auth\",\n \"authorization\",\n \"client_secret\",\n \"oauth_code\",\n \"passwd\",\n \"password\",\n \"refresh_token\",\n \"sig\",\n \"signature\",\n \"token\",\n].map(normalizeQueryKey));\n\nexport function detectBodyFormat(body: string, headers: Record<string, string>): TraceBodyFormat {\n if (body.length === 0) {\n return \"empty\";\n }\n const contentType = headerValue(headers, \"content-type\").toLowerCase();\n if (contentType.includes(\"json\")) {\n return \"json\";\n }\n if (contentType.includes(\"html\")) {\n return \"html\";\n }\n if (contentType.includes(\"xml\")) {\n return \"xml\";\n }\n if (contentType.includes(\"x-www-form-urlencoded\")) {\n return \"form\";\n }\n if (contentType.includes(\"octet-stream\")) {\n return \"binary\";\n }\n return detectBodyFormatFromText(body, contentType);\n}\n\nexport function compactTraceEvent(record: StoredTraceEvent): CompactTraceEvent {\n const event = record.event;\n const requestBody = compactBody(event.requestBodyPreview);\n const responseBody = compactBody(event.responseBodyPreview);\n return {\n id: event.id,\n sessionId: record.sessionId,\n requestId: record.requestId,\n timestamp: event.timestamp,\n instance: event.instance,\n method: event.method,\n path: event.path,\n url: redactSensitiveQueryValues(event.url),\n normalizedUrl: redactSensitiveQueryValues(event.normalizedUrl),\n status: event.status,\n durationMs: event.durationMs,\n requestBytes: event.requestBytes,\n responseBytes: event.responseBytes,\n requestBodyFormat: record.requestBodyFormat,\n responseBodyFormat: record.responseBodyFormat,\n requestBodyPreview: requestBody.preview,\n requestBodyPreviewRemainingChars: requestBody.remainingChars,\n responseBodyPreview: responseBody.preview,\n responseBodyPreviewRemainingChars: responseBody.remainingChars,\n requestBodyTruncated: event.requestBodyTruncated,\n responseBodyTruncated: event.responseBodyTruncated,\n droppedBeforeEvent: event.droppedBeforeEvent,\n source: event.source,\n traceId: event.traceId,\n correlationId: event.correlationId,\n };\n}\n\nfunction headerValue(headers: Record<string, string>, name: string): string {\n const lowerName = name.toLowerCase();\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lowerName) {\n return value;\n }\n }\n return \"\";\n}\n\nfunction detectBodyFormatFromText(body: string, contentType: string): TraceBodyFormat {\n const trimmed = body.trim();\n if (isJsonText(trimmed)) {\n return \"json\";\n }\n if (/^<!doctype\\s+html/i.test(trimmed) || /^<html(?:\\s|>)/i.test(trimmed)) {\n return \"html\";\n }\n if (/^<\\?xml(?:\\s|>)/i.test(trimmed) || /^<[A-Za-z_][\\w:.-]*(?:\\s|>|\\/>)/.test(trimmed)) {\n return \"xml\";\n }\n if (contentType.startsWith(\"text/\")) {\n return \"text\";\n }\n if (hasBinaryControlChars(body)) {\n return \"binary\";\n }\n return \"text\";\n}\n\nfunction isJsonText(text: string): boolean {\n if (!text.startsWith(\"{\") && !text.startsWith(\"[\")) {\n return false;\n }\n try {\n JSON.parse(text) as unknown;\n return true;\n } catch {\n return false;\n }\n}\n\nfunction hasBinaryControlChars(text: string): boolean {\n for (let index = 0; index < text.length; index += 1) {\n const code = text.charCodeAt(index);\n if (code <= 8 || code === 11 || code === 12 || (code >= 14 && code <= 31)) {\n return true;\n }\n }\n return false;\n}\n\nfunction compactBody(body: string): { readonly preview: string; readonly remainingChars: number } {\n let preview = \"\";\n let length = 0;\n for (const character of body) {\n if (length < COMPACT_BODY_PREVIEW_CHARS) {\n preview += character;\n }\n length += 1;\n }\n return {\n preview,\n remainingChars: Math.max(0, length - COMPACT_BODY_PREVIEW_CHARS),\n };\n}\n\nfunction redactSensitiveQueryValues(rawUrl: string): string {\n const queryIndex = rawUrl.indexOf(\"?\");\n if (queryIndex < 0) {\n return rawUrl;\n }\n const fragmentIndex = rawUrl.indexOf(\"#\", queryIndex);\n const queryEnd = fragmentIndex < 0 ? rawUrl.length : fragmentIndex;\n const query = rawUrl.slice(queryIndex + 1, queryEnd);\n const redacted = query.split(\"&\").map(redactQueryPart).join(\"&\");\n return `${rawUrl.slice(0, queryIndex + 1)}${redacted}${rawUrl.slice(queryEnd)}`;\n}\n\nfunction redactQueryPart(part: string): string {\n const separatorIndex = part.indexOf(\"=\");\n const rawKey = separatorIndex < 0 ? part : part.slice(0, separatorIndex);\n if (!SENSITIVE_QUERY_KEYS.has(normalizeQueryKey(rawKey))) {\n return part;\n }\n return `${rawKey}=redacted`;\n}\n\nfunction normalizeQueryKey(rawKey: string): string {\n try {\n return decodeURIComponent(rawKey).toLowerCase().replaceAll(/[^a-z0-9]/g, \"\");\n } catch {\n return rawKey.toLowerCase().replaceAll(/[^a-z0-9]/g, \"\");\n }\n}\n","import type { StoredTraceEvent } from \"./trace-store.js\";\n\nexport type TraceBodySide = \"request\" | \"response\";\nexport type TraceSearchBodySide = TraceBodySide | \"both\";\n\nexport interface TraceBodyInspectionOptions {\n readonly body: TraceBodySide;\n readonly path?: string;\n readonly limit?: number;\n readonly maxRows?: number;\n}\n\nexport interface TraceBodyInspectionRow {\n readonly path: string;\n readonly type: string;\n readonly value: string;\n}\n\nexport interface TraceBodyInspectionResult {\n readonly rows: readonly TraceBodyInspectionRow[];\n readonly totalRows: number;\n readonly rowsTruncated: boolean;\n}\n\nexport interface TraceSearchOptions {\n readonly body: TraceSearchBodySide;\n readonly limit: number;\n readonly previewLength?: number;\n}\n\nexport interface TraceSearchMatch {\n readonly sessionId: string;\n readonly requestId: string;\n readonly timestamp: string;\n readonly method: string;\n readonly normalizedUrl: string;\n readonly status: number | null;\n readonly body: TraceBodySide;\n readonly path: string;\n readonly offset?: number;\n readonly preview: string;\n}\n\nconst DEFAULT_BODY_LIMIT = 4000;\n\ninterface ParsedJson {\n readonly value: unknown;\n}\n\nexport function inspectTraceBody(\n record: StoredTraceEvent,\n options: TraceBodyInspectionOptions,\n): readonly TraceBodyInspectionRow[] {\n return inspectTraceBodyResult(record, options).rows;\n}\n\nexport function inspectTraceBodyResult(\n record: StoredTraceEvent,\n options: TraceBodyInspectionOptions,\n): TraceBodyInspectionResult {\n const limit = positive(\"limit\", options.limit ?? DEFAULT_BODY_LIMIT);\n const maxRows = positive(\"max rows\", options.maxRows ?? Number.MAX_SAFE_INTEGER);\n const pointer = options.path ?? \"\";\n const parsed = parseJsonBody(bodyText(record, options.body));\n const selected = resolvePointer(parsed, pointer);\n const rows = inspectionRows(selected, pointer, limit, maxRows);\n return {\n rows: rows.values,\n totalRows: rows.total,\n rowsTruncated: rows.total > rows.values.length,\n };\n}\n\nfunction inspectionRows(\n selected: unknown,\n pointer: string,\n valueLimit: number,\n maxRows: number,\n): { readonly values: readonly TraceBodyInspectionRow[]; readonly total: number } {\n if (Array.isArray(selected)) {\n const values = selected.slice(0, maxRows).map(\n (item, index) => inspectionRow(`${pointer}/${String(index)}`, item, valueLimit),\n );\n return { values, total: selected.length };\n }\n if (!isRecord(selected)) {\n return { values: [inspectionRow(pointer, selected, valueLimit)], total: 1 };\n }\n return objectInspectionRows(selected, pointer, valueLimit, maxRows);\n}\n\nfunction objectInspectionRows(\n selected: Record<string, unknown>,\n pointer: string,\n valueLimit: number,\n maxRows: number,\n): { readonly values: readonly TraceBodyInspectionRow[]; readonly total: number } {\n const values: TraceBodyInspectionRow[] = [];\n let total = 0;\n for (const key in selected) {\n if (!Object.hasOwn(selected, key)) {\n continue;\n }\n if (values.length < maxRows) {\n values.push(inspectionRow(`${pointer}/${escapePointerToken(key)}`, selected[key], valueLimit));\n }\n total += 1;\n }\n return { values, total };\n}\n\nexport function searchTraceRecords(\n records: readonly StoredTraceEvent[],\n searchTerm: string,\n options: TraceSearchOptions,\n): readonly TraceSearchMatch[] {\n const term = searchTerm.trim().toLowerCase();\n if (term.length === 0) {\n throw new Error(\"search text must not be empty\");\n }\n const limit = positive(\"limit\", options.limit);\n const previewLength = positive(\"preview length\", options.previewLength ?? 128);\n const matches: TraceSearchMatch[] = [];\n for (const record of records) {\n for (const side of selectedSides(options.body)) {\n const remaining = limit - matches.length;\n matches.push(...searchBody(record, side, term, remaining, previewLength));\n if (matches.length >= limit) {\n return matches;\n }\n }\n }\n return matches;\n}\n\nfunction searchBody(\n record: StoredTraceEvent,\n side: TraceBodySide,\n term: string,\n limit: number,\n previewLength: number,\n): readonly TraceSearchMatch[] {\n if (limit <= 0) {\n return [];\n }\n const body = bodyText(record, side);\n const parsed = tryParseJson(body);\n return parsed === undefined\n ? plainTextMatches(record, side, body, term, limit, previewLength)\n : jsonSearchMatches(record, side, parsed.value, term, limit, previewLength);\n}\n\nfunction plainTextMatches(\n record: StoredTraceEvent,\n side: TraceBodySide,\n text: string,\n term: string,\n limit: number,\n previewLength: number,\n): readonly TraceSearchMatch[] {\n const matches: TraceSearchMatch[] = [];\n const lowerText = text.toLowerCase();\n let offset = lowerText.indexOf(term);\n while (offset >= 0 && matches.length < limit) {\n const start = Math.max(0, offset - 32);\n matches.push(toSearchMatch(record, side, \"\", text.slice(start, start + previewLength).replaceAll(/[\\r\\n\\t]/g, \" \"), offset));\n offset = lowerText.indexOf(term, offset + Math.max(1, term.length));\n }\n return matches;\n}\n\nfunction jsonSearchMatches(\n record: StoredTraceEvent,\n side: TraceBodySide,\n root: unknown,\n term: string,\n limit: number,\n previewLength: number,\n): readonly TraceSearchMatch[] {\n const matches: TraceSearchMatch[] = [];\n const stack: { readonly path: string; readonly value: unknown }[] = [{ path: \"\", value: root }];\n while (stack.length > 0 && matches.length < limit) {\n const entry = stack.pop();\n if (entry === undefined) {\n break;\n }\n inspectJsonSearchEntry(record, side, entry, term, limit, previewLength, matches, stack);\n }\n return matches.slice(0, limit);\n}\n\nfunction inspectJsonSearchEntry(\n record: StoredTraceEvent,\n side: TraceBodySide,\n entry: { readonly path: string; readonly value: unknown },\n term: string,\n limit: number,\n previewLength: number,\n matches: TraceSearchMatch[],\n stack: { readonly path: string; readonly value: unknown }[],\n): void {\n if (typeof entry.value === \"object\" && entry.value !== null) {\n pushJsonChildren(record, side, entry, term, limit, previewLength, matches, stack);\n return;\n }\n const text = jsonScalarSearchText(entry.value);\n if (text.toLowerCase().includes(term)) {\n matches.push(toSearchMatch(record, side, entry.path, text.slice(0, previewLength)));\n }\n}\n\nfunction pushJsonChildren(\n record: StoredTraceEvent,\n side: TraceBodySide,\n entry: { readonly path: string; readonly value: unknown },\n term: string,\n limit: number,\n previewLength: number,\n matches: TraceSearchMatch[],\n stack: { readonly path: string; readonly value: unknown }[],\n): void {\n if (!Array.isArray(entry.value) && !isRecord(entry.value)) {\n return;\n }\n const entries = Array.isArray(entry.value)\n ? entry.value.map((item, index) => [String(index), item] as const)\n : Object.entries(entry.value);\n for (const [key, value] of entries.reverse()) {\n if (matches.length >= limit) {\n return;\n }\n const path = `${entry.path}/${escapePointerToken(key)}`;\n if (key.toLowerCase().includes(term)) {\n matches.push(toSearchMatch(record, side, path, jsonValueText(value, previewLength)));\n }\n stack.push({ path, value });\n }\n}\n\nfunction toSearchMatch(\n record: StoredTraceEvent,\n side: TraceBodySide,\n path: string,\n preview: string,\n offset?: number,\n): TraceSearchMatch {\n return {\n sessionId: record.sessionId,\n requestId: record.requestId,\n timestamp: record.event.timestamp,\n method: record.event.method,\n normalizedUrl: record.event.normalizedUrl,\n status: record.event.status,\n body: side,\n path,\n ...(offset === undefined ? {} : { offset }),\n preview,\n };\n}\n\nfunction selectedSides(body: TraceSearchBodySide): readonly TraceBodySide[] {\n return body === \"both\" ? [\"request\", \"response\"] : [body];\n}\n\nfunction bodyText(record: StoredTraceEvent, body: TraceBodySide): string {\n return body === \"request\" ? record.event.requestBodyPreview : record.event.responseBodyPreview;\n}\n\nfunction parseJsonBody(body: string): unknown {\n try {\n return JSON.parse(body) as unknown;\n } catch (error) {\n throw new Error(\"Saved trace body does not contain valid JSON\", { cause: error });\n }\n}\n\nfunction tryParseJson(body: string): ParsedJson | undefined {\n try {\n return { value: JSON.parse(body) as unknown };\n } catch {\n return undefined;\n }\n}\n\nfunction decodePointerToken(token: string): string {\n if (/~(?:[^01]|$)/.test(token)) {\n throw new Error(\"Invalid JSON Pointer escape\");\n }\n return token.replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\");\n}\n\nfunction pointerTokens(pointer: string): readonly string[] {\n if (pointer === \"\") {\n return [];\n }\n if (!pointer.startsWith(\"/\")) {\n throw new Error(\"JSON Pointer must be empty or start with /\");\n }\n return pointer.slice(1).split(\"/\").map(decodePointerToken);\n}\n\nfunction resolvePointer(root: unknown, pointer: string): unknown {\n let current = root;\n for (const token of pointerTokens(pointer)) {\n current = resolvePointerToken(current, token, pointer);\n }\n return current;\n}\n\nfunction resolvePointerToken(current: unknown, token: string, pointer: string): unknown {\n if (Array.isArray(current)) {\n const index = Number(token);\n if (!Number.isSafeInteger(index) || index < 0 || index >= current.length) {\n throw new Error(`JSON Pointer path \"${pointer}\" not found`);\n }\n return current[index];\n }\n if (isRecord(current) && Object.hasOwn(current, token)) {\n return current[token];\n }\n throw new Error(`JSON Pointer path \"${pointer}\" not found`);\n}\n\nfunction escapePointerToken(token: string): string {\n return token.replaceAll(\"~\", \"~0\").replaceAll(\"/\", \"~1\");\n}\n\nfunction inspectionRow(path: string, value: unknown, limit: number): TraceBodyInspectionRow {\n return { path, type: jsonType(value), value: jsonValueText(value, limit) };\n}\n\nfunction jsonType(value: unknown): string {\n if (value === null) {\n return \"null\";\n }\n if (Array.isArray(value)) {\n return \"array\";\n }\n return typeof value;\n}\n\nfunction jsonValueText(value: unknown, limit: number): string {\n if (Array.isArray(value)) {\n return `items=${String(value.length)}`;\n }\n if (typeof value === \"object\" && value !== null) {\n return `keys=${String(Object.keys(value).length)}`;\n }\n if (typeof value === \"string\") {\n return value.slice(0, limit);\n }\n if (value === null) {\n return \"null\";\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n return \"\";\n}\n\nfunction jsonScalarSearchText(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (value === null) {\n return \"null\";\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n return \"\";\n}\n\nfunction positive(name: string, value: number): number {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${name} must be a positive safe integer`);\n }\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { access, mkdir, readFile, readdir, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { detectBodyFormat, type TraceBodyFormat } from \"./trace-compact.js\";\nimport type { CfLiveTraceTarget, LiveTraceEvent } from \"./types.js\";\n\nconst SAPTOOLS_DIR_NAME = \".saptools\";\nconst CF_LIVE_TRACE_DIR_NAME = \"cf-live-trace\";\nconst SESSIONS_DIR_NAME = \"sessions\";\nconst EVENTS_DIR_NAME = \"events\";\nconst MANIFEST_FILE_NAME = \"manifest.json\";\nconst TRACE_TTL_MS = 2 * 60 * 60 * 1000;\nconst MAX_TARGET_SLUG_BYTES = 160;\nconst SESSION_ID_PATTERN = /^s(?:[0-9a-f]{8}|[0-9a-f]{16})$/;\nconst REQUEST_ID_PATTERN = /^r(?:[0-9a-f]{8}|[0-9a-f]{16})$/;\n\nexport interface TraceTargetIdentity {\n readonly region?: string;\n readonly apiEndpoint?: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n readonly instance: string;\n}\n\nexport interface TraceSession {\n readonly sessionId: string;\n readonly createdAt: string;\n readonly target: TraceTargetIdentity;\n readonly directory: string;\n readonly eventsDirectory: string;\n readonly manifestPath: string;\n}\n\nexport interface StoredTraceEvent {\n readonly version: 1;\n readonly sessionId: string;\n readonly requestId: string;\n readonly createdAt: string;\n readonly expiresAt: string;\n readonly target: TraceTargetIdentity;\n readonly requestBodyFormat: TraceBodyFormat;\n readonly responseBodyFormat: TraceBodyFormat;\n readonly event: LiveTraceEvent;\n}\n\nexport interface StoredTraceEventFile extends StoredTraceEvent {\n readonly backupPath: string;\n}\n\nexport interface TraceSessionSummary {\n readonly sessionId: string;\n readonly createdAt: string;\n readonly target: TraceTargetIdentity;\n readonly eventCount: number;\n readonly directory: string;\n}\n\nexport interface CreateTraceSessionInput {\n readonly target: CfLiveTraceTarget;\n}\n\nexport interface TraceStoreOptions {\n readonly saptoolsRoot?: string;\n readonly now?: () => Date;\n readonly sessionId?: string;\n readonly requestId?: () => string;\n}\n\nexport type TraceEventVisitor = (\n record: StoredTraceEventFile,\n) => boolean | Promise<boolean>;\n\ninterface StoredTraceSessionManifest {\n readonly version: 1;\n readonly sessionId: string;\n readonly createdAt: string;\n readonly target: TraceTargetIdentity;\n}\n\nexport function traceSessionsRoot(saptoolsRoot?: string): string {\n return join(saptoolsRoot ?? join(homedir(), SAPTOOLS_DIR_NAME), CF_LIVE_TRACE_DIR_NAME, SESSIONS_DIR_NAME);\n}\n\nexport async function createTraceSession(\n input: CreateTraceSessionInput,\n options: TraceStoreOptions = {},\n): Promise<TraceSession> {\n await pruneTraceSessions(options);\n const sessionId = resolveSessionId(options.sessionId);\n const createdAt = (options.now?.() ?? new Date()).toISOString();\n const target = toTargetIdentity(input.target);\n const directory = sessionDirectory(sessionId, options.saptoolsRoot);\n const eventsDirectory = join(directory, EVENTS_DIR_NAME);\n const manifestPath = join(directory, MANIFEST_FILE_NAME);\n await mkdir(eventsDirectory, { recursive: true, mode: 0o700 });\n await writeJsonFile(manifestPath, createManifest(sessionId, createdAt, target));\n return { sessionId, createdAt, target, directory, eventsDirectory, manifestPath };\n}\n\nexport async function writeTraceEvent(\n session: TraceSession,\n event: LiveTraceEvent,\n options: TraceStoreOptions = {},\n): Promise<StoredTraceEventFile> {\n const now = options.now?.() ?? new Date();\n const requestId = resolveRequestId(options.requestId?.());\n await ensureSessionManifest(session);\n const record: StoredTraceEvent = {\n version: 1,\n sessionId: session.sessionId,\n requestId,\n createdAt: now.toISOString(),\n expiresAt: new Date(now.getTime() + TRACE_TTL_MS).toISOString(),\n target: session.target,\n requestBodyFormat: detectBodyFormat(event.requestBodyPreview, event.requestHeaders),\n responseBodyFormat: detectBodyFormat(event.responseBodyPreview, event.responseHeaders),\n event,\n };\n const backupPath = join(session.eventsDirectory, eventFileName(record, now));\n await mkdir(session.eventsDirectory, { recursive: true, mode: 0o700 });\n await writeJsonFile(backupPath, record);\n return { ...record, backupPath };\n}\n\nexport async function readTraceEvent(\n sessionId: string,\n requestId: string,\n options: TraceStoreOptions = {},\n): Promise<StoredTraceEventFile> {\n const resolvedSessionId = resolveSessionId(sessionId);\n const resolvedRequestId = resolveRequestId(requestId);\n const entries = await listEventFilePaths(resolvedSessionId, options.saptoolsRoot);\n const candidates = entries.filter((path) => path.includes(`-${resolvedRequestId}-`));\n for (const path of candidates) {\n const record = await readStoredTraceEvent(path, resolvedSessionId);\n if (record === undefined || isExpired(record, options)) {\n await rm(path, { force: true });\n continue;\n }\n if (record.requestId === resolvedRequestId) {\n return record;\n }\n }\n throw new Error(\"Saved trace request not found or expired\");\n}\n\nexport async function listTraceEvents(\n sessionId: string,\n options: TraceStoreOptions = {},\n): Promise<readonly StoredTraceEventFile[]> {\n const records: StoredTraceEventFile[] = [];\n await visitTraceEvents(sessionId, (record) => {\n records.push(record);\n return true;\n }, options);\n return records;\n}\n\nexport async function visitTraceEvents(\n sessionId: string,\n visitor: TraceEventVisitor,\n options: TraceStoreOptions = {},\n): Promise<void> {\n const resolvedSessionId = resolveSessionId(sessionId);\n const entries = await listEventFilePaths(resolvedSessionId, options.saptoolsRoot);\n for (const path of entries) {\n const record = await readStoredTraceEvent(path, resolvedSessionId);\n if (record === undefined || isExpired(record, options)) {\n await rm(path, { force: true });\n continue;\n }\n if (!await visitor(record)) {\n return;\n }\n }\n}\n\nexport async function listTraceSessions(options: TraceStoreOptions = {}): Promise<readonly TraceSessionSummary[]> {\n await pruneTraceSessions(options);\n const sessionIds = await listSessionIds(options.saptoolsRoot);\n const summaries = await Promise.all(sessionIds.map(async (sessionId) => await readSessionSummary(sessionId, options)));\n return summaries\n .filter((summary): summary is TraceSessionSummary => summary !== undefined)\n .sort((left, right) => left.createdAt.localeCompare(right.createdAt));\n}\n\nexport async function pruneTraceSessions(options: TraceStoreOptions = {}): Promise<number> {\n const sessionIds = await listSessionIds(options.saptoolsRoot);\n const now = (options.now?.() ?? new Date()).getTime();\n let removed = 0;\n for (const sessionId of sessionIds) {\n removed += await pruneSession(sessionId, now, options.saptoolsRoot);\n }\n return removed;\n}\n\nfunction toTargetIdentity(target: CfLiveTraceTarget): TraceTargetIdentity {\n return {\n ...(target.region === undefined ? {} : { region: target.region }),\n ...(target.apiEndpoint === undefined ? {} : { apiEndpoint: target.apiEndpoint }),\n org: target.org,\n space: target.space,\n app: target.app,\n instance: String(target.instanceIndex ?? 0),\n };\n}\n\nfunction createManifest(\n sessionId: string,\n createdAt: string,\n target: TraceTargetIdentity,\n): StoredTraceSessionManifest {\n return { version: 1, sessionId, createdAt, target };\n}\n\nasync function ensureSessionManifest(session: TraceSession): Promise<void> {\n try {\n await access(session.manifestPath);\n return;\n } catch (error) {\n if (!isNodeError(error, \"ENOENT\")) {\n throw error;\n }\n }\n await mkdir(session.eventsDirectory, { recursive: true, mode: 0o700 });\n await writeJsonFile(\n session.manifestPath,\n createManifest(session.sessionId, session.createdAt, session.target),\n );\n}\n\nfunction isExpired(record: StoredTraceEvent, options: TraceStoreOptions): boolean {\n const now = (options.now?.() ?? new Date()).getTime();\n return Date.parse(record.expiresAt) <= now;\n}\n\nasync function readSessionSummary(\n sessionId: string,\n options: TraceStoreOptions,\n): Promise<TraceSessionSummary | undefined> {\n const manifest = await readStoredManifest(manifestPath(sessionId, options.saptoolsRoot));\n if (manifest?.sessionId !== sessionId) {\n return undefined;\n }\n const eventCount = (await listEventFilePaths(sessionId, options.saptoolsRoot)).length;\n return {\n sessionId,\n createdAt: manifest.createdAt,\n target: manifest.target,\n eventCount,\n directory: sessionDirectory(sessionId, options.saptoolsRoot),\n };\n}\n\nasync function pruneSession(sessionId: string, now: number, saptoolsRoot?: string): Promise<number> {\n const manifest = await readStoredManifest(manifestPath(sessionId, saptoolsRoot));\n const eventPaths = await listEventFilePaths(sessionId, saptoolsRoot);\n let removed = 0;\n let remaining = 0;\n for (const path of eventPaths) {\n const expiresAt = eventPathExpiresAt(path) ?? await storedEventExpiresAt(path);\n if (expiresAt === undefined || expiresAt <= now) {\n await rm(path, { force: true });\n removed += 1;\n } else {\n remaining += 1;\n }\n }\n if (remaining === 0 && isManifestExpiredOrMissing(manifest, now)) {\n await rm(sessionDirectory(sessionId, saptoolsRoot), { recursive: true, force: true });\n }\n return removed;\n}\n\nasync function storedEventExpiresAt(path: string): Promise<number | undefined> {\n const record = await readStoredTraceEvent(path);\n return record === undefined ? undefined : Date.parse(record.expiresAt);\n}\n\nfunction isManifestExpiredOrMissing(manifest: StoredTraceSessionManifest | undefined, now: number): boolean {\n if (manifest === undefined) {\n return true;\n }\n return Date.parse(manifest.createdAt) + TRACE_TTL_MS <= now;\n}\n\nasync function listSessionIds(saptoolsRoot?: string): Promise<readonly string[]> {\n try {\n const entries = await readdir(traceSessionsRoot(saptoolsRoot), { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory() && SESSION_ID_PATTERN.test(entry.name))\n .map((entry) => entry.name);\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return [];\n }\n throw error;\n }\n}\n\nasync function listEventFilePaths(sessionId: string, saptoolsRoot?: string): Promise<readonly string[]> {\n try {\n const directory = eventsDirectory(sessionId, saptoolsRoot);\n const entries = await readdir(directory, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".json\"))\n .map((entry) => join(directory, entry.name))\n .sort(compareEventPaths);\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return [];\n }\n throw error;\n }\n}\n\nfunction compareEventPaths(left: string, right: string): number {\n const leftTimestamp = eventPathTimestamp(left);\n const rightTimestamp = eventPathTimestamp(right);\n return leftTimestamp.localeCompare(rightTimestamp) || left.localeCompare(right);\n}\n\nfunction eventPathTimestamp(path: string): string {\n return /-(\\d{8}T\\d{9}Z)\\.json$/.exec(path)?.[1] ?? \"\";\n}\n\nfunction eventPathExpiresAt(path: string): number | undefined {\n const compact = eventPathTimestamp(path);\n if (compact.length === 0) {\n return undefined;\n }\n const iso = compact.replace(\n /^(\\d{4})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})(\\d{2})(\\d{3})Z$/,\n \"$1-$2-$3T$4:$5:$6.$7Z\",\n );\n const createdAt = Date.parse(iso);\n return Number.isNaN(createdAt) ? undefined : createdAt + TRACE_TTL_MS;\n}\n\nasync function readStoredManifest(path: string): Promise<StoredTraceSessionManifest | undefined> {\n const parsed = await readJsonFile(path);\n return parsed !== undefined && isStoredManifest(parsed) ? parsed : undefined;\n}\n\nasync function readStoredTraceEvent(\n path: string,\n expectedSessionId?: string,\n): Promise<StoredTraceEventFile | undefined> {\n const parsed = await readJsonFile(path);\n if (parsed === undefined || !isStoredTraceEvent(parsed)) {\n return undefined;\n }\n if (expectedSessionId !== undefined && parsed.sessionId !== expectedSessionId) {\n return undefined;\n }\n return { ...parsed, backupPath: path };\n}\n\nasync function readJsonFile(path: string): Promise<unknown> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return undefined;\n }\n throw error;\n }\n try {\n return JSON.parse(raw) as unknown;\n } catch (error) {\n if (!(error instanceof SyntaxError)) {\n throw error;\n }\n return undefined;\n }\n}\n\nasync function writeJsonFile(path: string, value: unknown): Promise<void> {\n const temporaryPath = `${path}.tmp-${process.pid.toString()}-${randomHex(4)}`;\n let renamed = false;\n try {\n await writeFile(temporaryPath, `${JSON.stringify(value, null, 2)}\\n`, {\n encoding: \"utf8\",\n mode: 0o600,\n });\n await rename(temporaryPath, path);\n renamed = true;\n } finally {\n if (!renamed) {\n await rm(temporaryPath, { force: true });\n }\n }\n}\n\nfunction eventFileName(record: StoredTraceEvent, now: Date): string {\n const parts = [\n targetSlug(record.target),\n record.sessionId,\n record.requestId,\n fileTimestamp(now),\n ].join(\"-\");\n return `${parts}.json`;\n}\n\nfunction targetSlug(target: TraceTargetIdentity): string {\n const regionOrApi = target.region ?? target.apiEndpoint ?? \"api\";\n const fullSlug = [regionOrApi, target.org, target.space, target.app]\n .map(sanitizePathPart)\n .join(\"-\");\n if (Buffer.byteLength(fullSlug) <= MAX_TARGET_SLUG_BYTES) {\n return fullSlug;\n }\n const hash = createHash(\"sha256\").update(fullSlug).digest(\"hex\").slice(0, 12);\n const prefix = fullSlug.slice(0, MAX_TARGET_SLUG_BYTES - hash.length - 1).replace(/-+$/, \"\");\n return `${prefix}-${hash}`;\n}\n\nfunction sanitizePathPart(value: string): string {\n const sanitized = value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n return sanitized.length === 0 ? \"unknown\" : sanitized;\n}\n\nfunction fileTimestamp(now: Date): string {\n return now.toISOString().replaceAll(\"-\", \"\").replaceAll(\":\", \"\").replace(\".\", \"\");\n}\n\nfunction sessionDirectory(sessionId: string, saptoolsRoot?: string): string {\n return join(traceSessionsRoot(saptoolsRoot), sessionId);\n}\n\nfunction eventsDirectory(sessionId: string, saptoolsRoot?: string): string {\n return join(sessionDirectory(sessionId, saptoolsRoot), EVENTS_DIR_NAME);\n}\n\nfunction manifestPath(sessionId: string, saptoolsRoot?: string): string {\n return join(sessionDirectory(sessionId, saptoolsRoot), MANIFEST_FILE_NAME);\n}\n\nfunction resolveSessionId(value: string | undefined): string {\n const sessionId = value ?? `s${randomHex(8)}`;\n if (!SESSION_ID_PATTERN.test(sessionId)) {\n throw new Error(\"Invalid trace session id\");\n }\n return sessionId;\n}\n\nfunction resolveRequestId(value: string | undefined): string {\n const requestId = value ?? `r${randomHex(8)}`;\n if (!REQUEST_ID_PATTERN.test(requestId)) {\n throw new Error(\"Invalid trace request id\");\n }\n return requestId;\n}\n\nfunction randomHex(bytes: number): string {\n return randomBytes(bytes).toString(\"hex\");\n}\n\nfunction isStoredManifest(value: unknown): value is StoredTraceSessionManifest {\n return (\n isRecord(value) &&\n value[\"version\"] === 1 &&\n isSessionId(value[\"sessionId\"]) &&\n isIsoTimestamp(value[\"createdAt\"]) &&\n isTraceTargetIdentity(value[\"target\"])\n );\n}\n\nfunction isStoredTraceEvent(value: unknown): value is StoredTraceEvent {\n return (\n isRecord(value) &&\n value[\"version\"] === 1 &&\n isStoredEventMetadata(value) &&\n isTraceTargetIdentity(value[\"target\"]) &&\n isTraceBodyFormat(value[\"requestBodyFormat\"]) &&\n isTraceBodyFormat(value[\"responseBodyFormat\"]) &&\n isLiveTraceEvent(value[\"event\"])\n );\n}\n\nfunction isStoredEventMetadata(value: Record<string, unknown>): boolean {\n return (\n isSessionId(value[\"sessionId\"]) &&\n isRequestId(value[\"requestId\"]) &&\n isIsoTimestamp(value[\"createdAt\"]) &&\n isIsoTimestamp(value[\"expiresAt\"])\n );\n}\n\nfunction isTraceTargetIdentity(value: unknown): value is TraceTargetIdentity {\n return (\n isRecord(value) &&\n optionalString(value[\"region\"]) &&\n optionalString(value[\"apiEndpoint\"]) &&\n typeof value[\"org\"] === \"string\" &&\n typeof value[\"space\"] === \"string\" &&\n typeof value[\"app\"] === \"string\" &&\n typeof value[\"instance\"] === \"string\"\n );\n}\n\nfunction isLiveTraceEvent(value: unknown): value is LiveTraceEvent {\n return (\n isRecord(value) &&\n hasLiveTraceStrings(value) &&\n hasLiveTraceMetrics(value) &&\n isStringRecord(value[\"requestHeaders\"]) &&\n isStringRecord(value[\"responseHeaders\"]) &&\n typeof value[\"requestBodyTruncated\"] === \"boolean\" &&\n typeof value[\"responseBodyTruncated\"] === \"boolean\" &&\n value[\"source\"] === \"runtime-http\" &&\n optionalNullableString(value[\"correlationId\"])\n );\n}\n\nfunction hasLiveTraceStrings(value: Record<string, unknown>): boolean {\n const fields = [\n \"id\",\n \"appId\",\n \"instance\",\n \"method\",\n \"path\",\n \"url\",\n \"normalizedUrl\",\n \"requestBodyPreview\",\n \"responseBodyPreview\",\n \"traceId\",\n ];\n return isIsoTimestamp(value[\"timestamp\"]) && fields.every((field) => typeof value[field] === \"string\");\n}\n\nfunction hasLiveTraceMetrics(value: Record<string, unknown>): boolean {\n return (\n isNullableFiniteNumber(value[\"status\"]) &&\n isNullableNonNegativeNumber(value[\"durationMs\"]) &&\n isNonNegativeFiniteNumber(value[\"requestBytes\"]) &&\n isNonNegativeFiniteNumber(value[\"responseBytes\"]) &&\n isNonNegativeFiniteNumber(value[\"droppedBeforeEvent\"])\n );\n}\n\nfunction isTraceBodyFormat(value: unknown): value is TraceBodyFormat {\n return (\n value === \"empty\" ||\n value === \"json\" ||\n value === \"xml\" ||\n value === \"html\" ||\n value === \"form\" ||\n value === \"text\" ||\n value === \"binary\" ||\n value === \"unknown\"\n );\n}\n\nfunction optionalString(value: unknown): boolean {\n return value === undefined || typeof value === \"string\";\n}\n\nfunction optionalNullableString(value: unknown): boolean {\n return value === null || typeof value === \"string\";\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return isRecord(value) && Object.values(value).every((entry) => typeof entry === \"string\");\n}\n\nfunction isSessionId(value: unknown): value is string {\n return typeof value === \"string\" && SESSION_ID_PATTERN.test(value);\n}\n\nfunction isRequestId(value: unknown): value is string {\n return typeof value === \"string\" && REQUEST_ID_PATTERN.test(value);\n}\n\nfunction isIsoTimestamp(value: unknown): value is string {\n if (typeof value !== \"string\") {\n return false;\n }\n const parsed = new Date(value);\n return !Number.isNaN(parsed.getTime()) && parsed.toISOString() === value;\n}\n\nfunction isNullableFiniteNumber(value: unknown): boolean {\n return value === null || isFiniteNumber(value);\n}\n\nfunction isNullableNonNegativeNumber(value: unknown): boolean {\n return value === null || isNonNegativeFiniteNumber(value);\n}\n\nfunction isNonNegativeFiniteNumber(value: unknown): boolean {\n return isFiniteNumber(value) && value >= 0;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return isRecord(error) && error[\"code\"] === code;\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 | Promise<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 MAX_DRAIN_EVALUATE_TIMEOUT_MS = 60_000;\nconst DRAIN_BODY_BUDGET_BYTES = 8 * 1024 * 1024;\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 summaryEvents: LiveTraceEvent[] = [];\n private consecutiveDrainTimeouts = 0;\n private drainTask: Promise<void> | undefined;\n private inspectorClient: InspectorRuntimeClient | undefined;\n private pollTimer: NodeJS.Timeout | undefined;\n private pendingDrainAcknowledgement: string | null = null;\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 this.pendingDrainAcknowledgement = null;\n this.summaryEvents.splice(0);\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 this.startDrain(maxBodyBytes);\n }, DRAIN_INTERVAL_MS);\n }\n\n private startDrain(maxBodyBytes: number): void {\n if (this.drainTask !== undefined || this.inspectorClient === undefined || this.state !== \"streaming\") {\n return;\n }\n const task = this.drainTraceEvents(maxBodyBytes);\n this.drainTask = task;\n void task.then(\n () => {\n this.clearDrainTask(task);\n },\n () => {\n this.clearDrainTask(task);\n },\n );\n }\n\n private clearDrainTask(task: Promise<void>): void {\n if (this.drainTask === task) {\n this.drainTask = undefined;\n }\n }\n\n private async drainTraceEvents(maxBodyBytes: number): Promise<void> {\n const batchSize = resolveDrainBatchSize(maxBodyBytes);\n try {\n const payload = await this.requireInspector().evaluate(\n buildDrainExpression(\n batchSize,\n resolveDrainTransportBodyLimit(maxBodyBytes),\n this.pendingDrainAcknowledgement,\n ),\n resolveDrainEvaluateTimeout(maxBodyBytes, batchSize),\n );\n this.consecutiveDrainTimeouts = 0;\n try {\n await this.publishDrainedEvents(payload, maxBodyBytes);\n } catch (error) {\n await this.handleEventHandlerFailure(error);\n }\n } catch (error) {\n await this.handleDrainFailure(error);\n }\n }\n\n private async publishDrainedEvents(payload: unknown, maxBodyBytes: number): Promise<void> {\n const drained = parseDrainResult(payload, { appId: this.options.target.app, maxBodyBytes });\n if (drained.events.length > 0) {\n await this.options.onEvents?.(drained.events);\n this.publishSummary(drained.events);\n }\n this.pendingDrainAcknowledgement = drained.drainId;\n }\n\n private publishSummary(events: readonly LiveTraceEvent[]): void {\n if (this.options.onSummary === undefined) {\n return;\n }\n this.summaryEvents.push(...events.map(toSummaryEvent));\n this.summaryEvents.splice(0, Math.max(0, this.summaryEvents.length - RUNTIME_QUEUE_SIZE));\n this.options.onSummary(buildUrlSummaries(this.summaryEvents));\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, false);\n this.postState(\"error\", \"Runtime HTTP trace connection was lost.\", false, true);\n }\n\n private async handleEventHandlerFailure(error: unknown): Promise<void> {\n this.log(`Live Trace event handler failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false, false);\n this.postState(\"error\", \"Trace event handler failed.\", false, true);\n }\n\n private async stopRuntimeTrace(\n uninstallRuntimeHook: boolean,\n waitForDrain = true,\n ): Promise<boolean> {\n this.stopPolling();\n if (waitForDrain) {\n await this.drainTask;\n }\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 const maxBodyBytes = options.maxBodyBytes ?? 4096;\n if (!Number.isSafeInteger(maxBodyBytes) || maxBodyBytes <= 0) {\n throw new Error(\"maxBodyBytes must be a positive safe integer.\");\n }\n const runtimeQueueSize = options.runtimeQueueSize ?? RUNTIME_QUEUE_SIZE;\n if (!Number.isSafeInteger(runtimeQueueSize) || runtimeQueueSize <= 0) {\n throw new Error(\"runtimeQueueSize must be a positive safe integer.\");\n }\n return {\n captureHeaders: options.captureHeaders ?? true,\n captureRequestBody: options.captureRequestBody ?? true,\n captureResponseBody: options.captureResponseBody ?? true,\n maxBodyBytes,\n runtimeQueueSize,\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 ? maxBodyBytes : 1;\n}\n\nfunction resolveDrainBatchSize(maxBodyBytes: number): number {\n const perEventBytes = Math.max(1, maxBodyBytes * 2);\n return Math.max(1, Math.min(DRAIN_BATCH_SIZE, Math.floor(DRAIN_BODY_BUDGET_BYTES / perEventBytes)));\n}\n\nfunction resolveDrainEvaluateTimeout(maxBodyBytes: number, batchSize: number): number {\n const estimatedBytes = Math.min(Number.MAX_SAFE_INTEGER, maxBodyBytes * 2 * batchSize);\n const extraMegabytes = Math.ceil(Math.max(0, estimatedBytes - 1_000_000) / 1_000_000);\n return Math.min(MAX_DRAIN_EVALUATE_TIMEOUT_MS, DRAIN_EVALUATE_TIMEOUT_MS + extraMegabytes * 5_000);\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\nfunction toSummaryEvent(event: LiveTraceEvent): LiveTraceEvent {\n return {\n ...event,\n requestHeaders: {},\n responseHeaders: {},\n requestBodyPreview: \"\",\n responseBodyPreview: \"\",\n };\n}\n"],"mappings":"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","names":["Buffer","isRecord","eventsDirectory","manifestPath","isRecord","rm","join","isRecord"]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime-source.ts","../src/preview.ts","../src/payload.ts","../src/summary.ts","../src/trace-compact.ts","../src/trace-inspect.ts","../src/trace-store.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 = 3;\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 let staleCleanup = null;\n if (existing && typeof existing.uninstall === 'function') {\n try {\n const cleanup = existing.uninstall();\n if (cleanup && typeof cleanup.then === 'function') {\n staleCleanup = Promise.resolve(cleanup).catch(() => undefined);\n }\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 nextDrainId: 1,\n pendingDrain: null\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 chunkBuffer = (chunk) => {\n if (!BufferCtor || chunk === undefined || chunk === null) return null;\n if (BufferCtor.isBuffer(chunk)) return chunk;\n if (typeof chunk === 'string' || chunk instanceof Uint8Array) return BufferCtor.from(chunk);\n return null;\n };\n const textByteLength = (text) => BufferCtor ? BufferCtor.byteLength(text) : text.length;\n const chunkByteLength = (chunk) => {\n if (chunk === undefined || chunk === null) return 0;\n if (BufferCtor && BufferCtor.isBuffer(chunk)) return chunk.length;\n if (chunk instanceof Uint8Array) return chunk.byteLength;\n return textByteLength(typeof chunk === 'string' ? chunk : '');\n };\n const truncateTextToBytes = (text, maxBytes) => {\n if (!BufferCtor) return text.slice(0, maxBytes);\n const encoded = BufferCtor.from(text);\n if (encoded.length <= maxBytes) return text;\n let boundary = Math.min(maxBytes, encoded.length);\n while (boundary > 0 && encoded[boundary] !== undefined && (encoded[boundary] & 0xc0) === 0x80) {\n boundary -= 1;\n }\n return encoded.subarray(0, boundary).toString('utf8');\n };\n const appendPreview = (chunks, currentBytes, chunk, enabled) => {\n if (!enabled) return currentBytes;\n const maxBytes = Math.floor(Number(state.options.maxBodyBytes) || 0);\n if (maxBytes <= 0) return currentBytes;\n const remaining = maxBytes - currentBytes;\n if (remaining <= 0) return currentBytes;\n const buffer = chunkBuffer(chunk);\n if (buffer) {\n const addition = buffer.subarray(0, remaining);\n chunks.push(addition);\n return currentBytes + addition.length;\n }\n const text = chunkText(chunk);\n const addition = truncateTextToBytes(text, remaining);\n chunks.push(addition);\n return currentBytes + textByteLength(addition);\n };\n const completeUtf8Length = (buffer) => {\n if (!buffer || buffer.length === 0) return 0;\n let start = buffer.length - 1;\n while (start > 0 && (buffer[start] & 0xc0) === 0x80) start -= 1;\n const lead = buffer[start];\n const expected = lead <= 0x7f ? 1 : lead <= 0xdf ? 2 : lead <= 0xef ? 3 : lead <= 0xf7 ? 4 : 1;\n return buffer.length - start < expected ? start : buffer.length;\n };\n const previewText = (chunks, retainedBytes) => {\n if (!BufferCtor) {\n const text = chunks.join('');\n return { text, bytes: textByteLength(text) };\n }\n const buffer = BufferCtor.concat(chunks, retainedBytes);\n const completeBytes = completeUtf8Length(buffer);\n return { text: buffer.subarray(0, completeBytes).toString('utf8'), bytes: completeBytes };\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 const requestPreviewChunks = [];\n const responsePreviewChunks = [];\n let requestPreviewBytes = 0;\n let responsePreviewBytes = 0;\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 requestBytes += chunkByteLength(args[0]);\n requestPreviewBytes = appendPreview(requestPreviewChunks, requestPreviewBytes, args[0], state.options.captureRequestBody);\n }\n return originalReqEmit.apply(this, [eventName, ...args]);\n };\n res.write = function patchedWrite(chunk, ...args) {\n responseBytes += chunkByteLength(chunk);\n responsePreviewBytes = appendPreview(responsePreviewChunks, responsePreviewBytes, chunk, state.options.captureResponseBody);\n return originalWrite.apply(this, [chunk, ...args]);\n };\n res.end = function patchedEnd(chunk, ...args) {\n if (chunk !== undefined) {\n responseBytes += chunkByteLength(chunk);\n responsePreviewBytes = appendPreview(responsePreviewChunks, responsePreviewBytes, 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 const requestPreview = previewText(requestPreviewChunks, requestPreviewBytes);\n const responsePreview = previewText(responsePreviewChunks, responsePreviewBytes);\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.text,\n responseBodyPreview: responsePreview.text,\n requestBodyTruncated: state.options.captureRequestBody && state.options.maxBodyBytes > 0 && requestBytes > requestPreview.bytes,\n responseBodyTruncated: state.options.captureResponseBody && state.options.maxBodyBytes > 0 && responseBytes > responsePreview.bytes,\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, maxBytes) => {\n const preview = event[previewKey];\n if (maxBytes <= 0 || typeof preview !== 'string' || textByteLength(preview) <= maxBytes) return event;\n return { ...event, [previewKey]: truncateTextToBytes(preview, maxBytes), [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 acknowledgeDrain = (drainId) => {\n const pending = state.pendingDrain;\n if (!pending || drainId !== pending.id) return;\n const drainedEvents = new Set(pending.sourceEvents);\n state.queue = state.queue.filter((event) => !drainedEvents.has(event));\n state.pendingDrain = null;\n };\n const drainResult = () => {\n const pending = state.pendingDrain;\n if (!pending) {\n return { drainId: null, events: [], droppedCount: state.droppedCount, queueSize: state.queue.length };\n }\n return {\n drainId: pending.id,\n events: pending.events,\n droppedCount: state.droppedCount,\n queueSize: state.queue.length\n };\n };\n const api = {\n version: runtimeVersion,\n async install(options) {\n if (staleCleanup) {\n await staleCleanup;\n staleCleanup = null;\n }\n state.options = {\n ...state.options,\n ...options,\n maxBodyBytes: toTransportLimit(options && options.maxBodyBytes),\n maxEvents: Math.max(1, Math.floor(Number(options && options.maxEvents) || 1))\n };\n state.queue = [];\n state.pendingDrain = null;\n state.droppedCount = 0;\n state.seen = new WeakSet();\n state.nextId = 1;\n state.nextDrainId = 1;\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, acknowledgedDrainId) {\n acknowledgeDrain(acknowledgedDrainId);\n if (state.pendingDrain) return drainResult();\n const count = Math.max(0, Math.min(Number(maxCount) || 0, state.queue.length));\n const transportLimit = toTransportLimit(maxTransportBodyBytes);\n if (count === 0) return drainResult();\n const sourceEvents = state.queue.slice(0, count);\n state.pendingDrain = {\n id: 'd' + String(state.nextDrainId++),\n sourceEvents,\n events: sourceEvents.map((event) => eventForDrain(event, transportLimit))\n };\n return drainResult();\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 state.queue = [];\n state.pendingDrain = null;\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(\n maxCount: number,\n maxTransportBodyBytes: number,\n acknowledgedDrainId: string | null = null,\n): string {\n const acknowledgement = JSON.stringify(acknowledgedDrainId);\n return `globalThis.${CF_LIVE_TRACE_GLOBAL_NAME}?.drainEvents(${String(maxCount)}, ${String(maxTransportBodyBytes)}, ${acknowledgement}) ?? { drainId: null, 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 { Buffer } from \"node:buffer\";\n\nexport interface PreviewTruncationResult {\n readonly preview: string;\n readonly truncated: boolean;\n}\n\nexport function truncatePreview(preview: string, maxBytes: number): PreviewTruncationResult {\n if (maxBytes <= 0) {\n return { preview, truncated: false };\n }\n const encoded = Buffer.from(preview);\n if (encoded.length <= maxBytes) {\n return { preview, truncated: false };\n }\n return {\n preview: encoded.subarray(0, utf8Boundary(encoded, maxBytes)).toString(\"utf8\"),\n truncated: true,\n };\n}\n\nfunction utf8Boundary(encoded: Buffer, maxBytes: number): number {\n let boundary = Math.min(maxBytes, encoded.length);\n while (boundary > 0 && isContinuationByte(encoded[boundary])) {\n boundary -= 1;\n }\n return boundary;\n}\n\nfunction isContinuationByte(value: number | undefined): boolean {\n return value !== undefined && (value & 0xc0) === 0x80;\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 { drainId: null, events: [], droppedCount: 0, queueSize: 0 };\n }\n const rawEvents = Array.isArray(payload[\"events\"]) ? payload[\"events\"] : [];\n return {\n drainId: readDrainId(payload[\"drainId\"]),\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 readDrainId(value: unknown): string | null {\n return typeof value === \"string\" && /^d\\d+$/.test(value) ? value : null;\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 type { StoredTraceEvent } from \"./trace-store.js\";\n\nexport type TraceBodyFormat = \"empty\" | \"json\" | \"xml\" | \"html\" | \"form\" | \"text\" | \"binary\" | \"unknown\";\n\nexport interface CompactTraceEvent {\n readonly id: string;\n readonly sessionId: string;\n readonly requestId: string;\n readonly timestamp: string;\n readonly instance: string;\n readonly method: string;\n readonly path: string;\n readonly url: string;\n readonly normalizedUrl: string;\n readonly status: number | null;\n readonly durationMs: number | null;\n readonly requestBytes: number;\n readonly responseBytes: number;\n readonly requestBodyFormat: TraceBodyFormat;\n readonly responseBodyFormat: TraceBodyFormat;\n readonly requestBodyPreview: string;\n readonly requestBodyPreviewRemainingChars: number;\n readonly responseBodyPreview: string;\n readonly responseBodyPreviewRemainingChars: number;\n readonly requestBodyTruncated: boolean;\n readonly responseBodyTruncated: boolean;\n readonly droppedBeforeEvent: number;\n readonly source: \"runtime-http\";\n readonly traceId: string;\n readonly correlationId: string | null;\n}\n\nconst COMPACT_BODY_PREVIEW_CHARS = 128;\nconst SENSITIVE_QUERY_KEYS = new Set([\n \"access_token\",\n \"api_key\",\n \"auth\",\n \"authorization\",\n \"client_secret\",\n \"oauth_code\",\n \"passwd\",\n \"password\",\n \"refresh_token\",\n \"sig\",\n \"signature\",\n \"token\",\n].map(normalizeQueryKey));\n\nexport function detectBodyFormat(body: string, headers: Record<string, string>): TraceBodyFormat {\n if (body.length === 0) {\n return \"empty\";\n }\n const contentType = headerValue(headers, \"content-type\").toLowerCase();\n if (contentType.includes(\"json\")) {\n return \"json\";\n }\n if (contentType.includes(\"html\")) {\n return \"html\";\n }\n if (contentType.includes(\"xml\")) {\n return \"xml\";\n }\n if (contentType.includes(\"x-www-form-urlencoded\")) {\n return \"form\";\n }\n if (contentType.includes(\"octet-stream\")) {\n return \"binary\";\n }\n return detectBodyFormatFromText(body, contentType);\n}\n\nexport function compactTraceEvent(record: StoredTraceEvent): CompactTraceEvent {\n const event = record.event;\n const requestBody = compactBody(event.requestBodyPreview);\n const responseBody = compactBody(event.responseBodyPreview);\n return {\n id: event.id,\n sessionId: record.sessionId,\n requestId: record.requestId,\n timestamp: event.timestamp,\n instance: event.instance,\n method: event.method,\n path: event.path,\n url: redactSensitiveQueryValues(event.url),\n normalizedUrl: redactSensitiveQueryValues(event.normalizedUrl),\n status: event.status,\n durationMs: event.durationMs,\n requestBytes: event.requestBytes,\n responseBytes: event.responseBytes,\n requestBodyFormat: record.requestBodyFormat,\n responseBodyFormat: record.responseBodyFormat,\n requestBodyPreview: requestBody.preview,\n requestBodyPreviewRemainingChars: requestBody.remainingChars,\n responseBodyPreview: responseBody.preview,\n responseBodyPreviewRemainingChars: responseBody.remainingChars,\n requestBodyTruncated: event.requestBodyTruncated,\n responseBodyTruncated: event.responseBodyTruncated,\n droppedBeforeEvent: event.droppedBeforeEvent,\n source: event.source,\n traceId: event.traceId,\n correlationId: event.correlationId,\n };\n}\n\nfunction headerValue(headers: Record<string, string>, name: string): string {\n const lowerName = name.toLowerCase();\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lowerName) {\n return value;\n }\n }\n return \"\";\n}\n\nfunction detectBodyFormatFromText(body: string, contentType: string): TraceBodyFormat {\n const trimmed = body.trim();\n if (isJsonText(trimmed)) {\n return \"json\";\n }\n if (/^<!doctype\\s+html/i.test(trimmed) || /^<html(?:\\s|>)/i.test(trimmed)) {\n return \"html\";\n }\n if (/^<\\?xml(?:\\s|>)/i.test(trimmed) || /^<[A-Za-z_][\\w:.-]*(?:\\s|>|\\/>)/.test(trimmed)) {\n return \"xml\";\n }\n if (contentType.startsWith(\"text/\")) {\n return \"text\";\n }\n if (hasBinaryControlChars(body)) {\n return \"binary\";\n }\n return \"text\";\n}\n\nfunction isJsonText(text: string): boolean {\n if (!text.startsWith(\"{\") && !text.startsWith(\"[\")) {\n return false;\n }\n try {\n JSON.parse(text) as unknown;\n return true;\n } catch {\n return false;\n }\n}\n\nfunction hasBinaryControlChars(text: string): boolean {\n for (let index = 0; index < text.length; index += 1) {\n const code = text.charCodeAt(index);\n if (code <= 8 || code === 11 || code === 12 || (code >= 14 && code <= 31)) {\n return true;\n }\n }\n return false;\n}\n\nfunction compactBody(body: string): { readonly preview: string; readonly remainingChars: number } {\n let preview = \"\";\n let length = 0;\n for (const character of body) {\n if (length < COMPACT_BODY_PREVIEW_CHARS) {\n preview += character;\n }\n length += 1;\n }\n return {\n preview,\n remainingChars: Math.max(0, length - COMPACT_BODY_PREVIEW_CHARS),\n };\n}\n\nfunction redactSensitiveQueryValues(rawUrl: string): string {\n const queryIndex = rawUrl.indexOf(\"?\");\n if (queryIndex < 0) {\n return rawUrl;\n }\n const fragmentIndex = rawUrl.indexOf(\"#\", queryIndex);\n const queryEnd = fragmentIndex < 0 ? rawUrl.length : fragmentIndex;\n const query = rawUrl.slice(queryIndex + 1, queryEnd);\n const redacted = query.split(\"&\").map(redactQueryPart).join(\"&\");\n return `${rawUrl.slice(0, queryIndex + 1)}${redacted}${rawUrl.slice(queryEnd)}`;\n}\n\nfunction redactQueryPart(part: string): string {\n const separatorIndex = part.indexOf(\"=\");\n const rawKey = separatorIndex < 0 ? part : part.slice(0, separatorIndex);\n if (!SENSITIVE_QUERY_KEYS.has(normalizeQueryKey(rawKey))) {\n return part;\n }\n return `${rawKey}=redacted`;\n}\n\nfunction normalizeQueryKey(rawKey: string): string {\n try {\n return decodeURIComponent(rawKey).toLowerCase().replaceAll(/[^a-z0-9]/g, \"\");\n } catch {\n return rawKey.toLowerCase().replaceAll(/[^a-z0-9]/g, \"\");\n }\n}\n","import type { StoredTraceEvent } from \"./trace-store.js\";\n\nexport type TraceBodySide = \"request\" | \"response\";\nexport type TraceSearchBodySide = TraceBodySide | \"both\";\n\nexport interface TraceBodyInspectionOptions {\n readonly body: TraceBodySide;\n readonly path?: string;\n readonly limit?: number;\n readonly maxRows?: number;\n}\n\nexport interface TraceBodyInspectionRow {\n readonly path: string;\n readonly type: string;\n readonly value: string;\n}\n\nexport interface TraceBodyInspectionResult {\n readonly rows: readonly TraceBodyInspectionRow[];\n readonly totalRows: number;\n readonly rowsTruncated: boolean;\n}\n\nexport interface TraceSearchOptions {\n readonly body: TraceSearchBodySide;\n readonly limit: number;\n readonly previewLength?: number;\n}\n\nexport interface TraceSearchMatch {\n readonly sessionId: string;\n readonly requestId: string;\n readonly timestamp: string;\n readonly method: string;\n readonly normalizedUrl: string;\n readonly status: number | null;\n readonly body: TraceBodySide;\n readonly path: string;\n readonly offset?: number;\n readonly preview: string;\n}\n\nconst DEFAULT_BODY_LIMIT = 4000;\n\ninterface ParsedJson {\n readonly value: unknown;\n}\n\nexport function inspectTraceBody(\n record: StoredTraceEvent,\n options: TraceBodyInspectionOptions,\n): readonly TraceBodyInspectionRow[] {\n return inspectTraceBodyResult(record, options).rows;\n}\n\nexport function inspectTraceBodyResult(\n record: StoredTraceEvent,\n options: TraceBodyInspectionOptions,\n): TraceBodyInspectionResult {\n const limit = positive(\"limit\", options.limit ?? DEFAULT_BODY_LIMIT);\n const maxRows = positive(\"max rows\", options.maxRows ?? Number.MAX_SAFE_INTEGER);\n const pointer = options.path ?? \"\";\n const parsed = parseJsonBody(bodyText(record, options.body));\n const selected = resolvePointer(parsed, pointer);\n const rows = inspectionRows(selected, pointer, limit, maxRows);\n return {\n rows: rows.values,\n totalRows: rows.total,\n rowsTruncated: rows.total > rows.values.length,\n };\n}\n\nfunction inspectionRows(\n selected: unknown,\n pointer: string,\n valueLimit: number,\n maxRows: number,\n): { readonly values: readonly TraceBodyInspectionRow[]; readonly total: number } {\n if (Array.isArray(selected)) {\n const values = selected.slice(0, maxRows).map(\n (item, index) => inspectionRow(`${pointer}/${String(index)}`, item, valueLimit),\n );\n return { values, total: selected.length };\n }\n if (!isRecord(selected)) {\n return { values: [inspectionRow(pointer, selected, valueLimit)], total: 1 };\n }\n return objectInspectionRows(selected, pointer, valueLimit, maxRows);\n}\n\nfunction objectInspectionRows(\n selected: Record<string, unknown>,\n pointer: string,\n valueLimit: number,\n maxRows: number,\n): { readonly values: readonly TraceBodyInspectionRow[]; readonly total: number } {\n const values: TraceBodyInspectionRow[] = [];\n let total = 0;\n for (const key in selected) {\n if (!Object.hasOwn(selected, key)) {\n continue;\n }\n if (values.length < maxRows) {\n values.push(inspectionRow(`${pointer}/${escapePointerToken(key)}`, selected[key], valueLimit));\n }\n total += 1;\n }\n return { values, total };\n}\n\nexport function searchTraceRecords(\n records: readonly StoredTraceEvent[],\n searchTerm: string,\n options: TraceSearchOptions,\n): readonly TraceSearchMatch[] {\n const term = searchTerm.trim().toLowerCase();\n if (term.length === 0) {\n throw new Error(\"search text must not be empty\");\n }\n const limit = positive(\"limit\", options.limit);\n const previewLength = positive(\"preview length\", options.previewLength ?? 128);\n const matches: TraceSearchMatch[] = [];\n for (const record of records) {\n for (const side of selectedSides(options.body)) {\n const remaining = limit - matches.length;\n matches.push(...searchBody(record, side, term, remaining, previewLength));\n if (matches.length >= limit) {\n return matches;\n }\n }\n }\n return matches;\n}\n\nfunction searchBody(\n record: StoredTraceEvent,\n side: TraceBodySide,\n term: string,\n limit: number,\n previewLength: number,\n): readonly TraceSearchMatch[] {\n if (limit <= 0) {\n return [];\n }\n const body = bodyText(record, side);\n const parsed = tryParseJson(body);\n return parsed === undefined\n ? plainTextMatches(record, side, body, term, limit, previewLength)\n : jsonSearchMatches(record, side, parsed.value, term, limit, previewLength);\n}\n\nfunction plainTextMatches(\n record: StoredTraceEvent,\n side: TraceBodySide,\n text: string,\n term: string,\n limit: number,\n previewLength: number,\n): readonly TraceSearchMatch[] {\n const matches: TraceSearchMatch[] = [];\n const lowerText = text.toLowerCase();\n let offset = lowerText.indexOf(term);\n while (offset >= 0 && matches.length < limit) {\n const start = Math.max(0, offset - 32);\n matches.push(toSearchMatch(record, side, \"\", text.slice(start, start + previewLength).replaceAll(/[\\r\\n\\t]/g, \" \"), offset));\n offset = lowerText.indexOf(term, offset + Math.max(1, term.length));\n }\n return matches;\n}\n\nfunction jsonSearchMatches(\n record: StoredTraceEvent,\n side: TraceBodySide,\n root: unknown,\n term: string,\n limit: number,\n previewLength: number,\n): readonly TraceSearchMatch[] {\n const matches: TraceSearchMatch[] = [];\n const stack: { readonly path: string; readonly value: unknown }[] = [{ path: \"\", value: root }];\n while (stack.length > 0 && matches.length < limit) {\n const entry = stack.pop();\n if (entry === undefined) {\n break;\n }\n inspectJsonSearchEntry(record, side, entry, term, limit, previewLength, matches, stack);\n }\n return matches.slice(0, limit);\n}\n\nfunction inspectJsonSearchEntry(\n record: StoredTraceEvent,\n side: TraceBodySide,\n entry: { readonly path: string; readonly value: unknown },\n term: string,\n limit: number,\n previewLength: number,\n matches: TraceSearchMatch[],\n stack: { readonly path: string; readonly value: unknown }[],\n): void {\n if (typeof entry.value === \"object\" && entry.value !== null) {\n pushJsonChildren(record, side, entry, term, limit, previewLength, matches, stack);\n return;\n }\n const text = jsonScalarSearchText(entry.value);\n if (text.toLowerCase().includes(term)) {\n matches.push(toSearchMatch(record, side, entry.path, text.slice(0, previewLength)));\n }\n}\n\nfunction pushJsonChildren(\n record: StoredTraceEvent,\n side: TraceBodySide,\n entry: { readonly path: string; readonly value: unknown },\n term: string,\n limit: number,\n previewLength: number,\n matches: TraceSearchMatch[],\n stack: { readonly path: string; readonly value: unknown }[],\n): void {\n if (!Array.isArray(entry.value) && !isRecord(entry.value)) {\n return;\n }\n const entries = Array.isArray(entry.value)\n ? entry.value.map((item, index) => [String(index), item] as const)\n : Object.entries(entry.value);\n for (const [key, value] of entries.reverse()) {\n if (matches.length >= limit) {\n return;\n }\n const path = `${entry.path}/${escapePointerToken(key)}`;\n if (key.toLowerCase().includes(term)) {\n matches.push(toSearchMatch(record, side, path, jsonValueText(value, previewLength)));\n }\n stack.push({ path, value });\n }\n}\n\nfunction toSearchMatch(\n record: StoredTraceEvent,\n side: TraceBodySide,\n path: string,\n preview: string,\n offset?: number,\n): TraceSearchMatch {\n return {\n sessionId: record.sessionId,\n requestId: record.requestId,\n timestamp: record.event.timestamp,\n method: record.event.method,\n normalizedUrl: record.event.normalizedUrl,\n status: record.event.status,\n body: side,\n path,\n ...(offset === undefined ? {} : { offset }),\n preview,\n };\n}\n\nfunction selectedSides(body: TraceSearchBodySide): readonly TraceBodySide[] {\n return body === \"both\" ? [\"request\", \"response\"] : [body];\n}\n\nfunction bodyText(record: StoredTraceEvent, body: TraceBodySide): string {\n return body === \"request\" ? record.event.requestBodyPreview : record.event.responseBodyPreview;\n}\n\nfunction parseJsonBody(body: string): unknown {\n try {\n return JSON.parse(body) as unknown;\n } catch (error) {\n throw new Error(\"Saved trace body does not contain valid JSON\", { cause: error });\n }\n}\n\nfunction tryParseJson(body: string): ParsedJson | undefined {\n try {\n return { value: JSON.parse(body) as unknown };\n } catch {\n return undefined;\n }\n}\n\nfunction decodePointerToken(token: string): string {\n if (/~(?:[^01]|$)/.test(token)) {\n throw new Error(\"Invalid JSON Pointer escape\");\n }\n return token.replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\");\n}\n\nfunction pointerTokens(pointer: string): readonly string[] {\n if (pointer === \"\") {\n return [];\n }\n if (!pointer.startsWith(\"/\")) {\n throw new Error(\"JSON Pointer must be empty or start with /\");\n }\n return pointer.slice(1).split(\"/\").map(decodePointerToken);\n}\n\nfunction resolvePointer(root: unknown, pointer: string): unknown {\n let current = root;\n for (const token of pointerTokens(pointer)) {\n current = resolvePointerToken(current, token, pointer);\n }\n return current;\n}\n\nfunction resolvePointerToken(current: unknown, token: string, pointer: string): unknown {\n if (Array.isArray(current)) {\n const index = Number(token);\n if (!Number.isSafeInteger(index) || index < 0 || index >= current.length) {\n throw new Error(`JSON Pointer path \"${pointer}\" not found`);\n }\n return current[index];\n }\n if (isRecord(current) && Object.hasOwn(current, token)) {\n return current[token];\n }\n throw new Error(`JSON Pointer path \"${pointer}\" not found`);\n}\n\nfunction escapePointerToken(token: string): string {\n return token.replaceAll(\"~\", \"~0\").replaceAll(\"/\", \"~1\");\n}\n\nfunction inspectionRow(path: string, value: unknown, limit: number): TraceBodyInspectionRow {\n return { path, type: jsonType(value), value: jsonValueText(value, limit) };\n}\n\nfunction jsonType(value: unknown): string {\n if (value === null) {\n return \"null\";\n }\n if (Array.isArray(value)) {\n return \"array\";\n }\n return typeof value;\n}\n\nfunction jsonValueText(value: unknown, limit: number): string {\n if (Array.isArray(value)) {\n return `items=${String(value.length)}`;\n }\n if (typeof value === \"object\" && value !== null) {\n return `keys=${String(Object.keys(value).length)}`;\n }\n if (typeof value === \"string\") {\n return value.slice(0, limit);\n }\n if (value === null) {\n return \"null\";\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n return \"\";\n}\n\nfunction jsonScalarSearchText(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (value === null) {\n return \"null\";\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n return \"\";\n}\n\nfunction positive(name: string, value: number): number {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${name} must be a positive safe integer`);\n }\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { access, mkdir, readFile, readdir, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { detectBodyFormat, type TraceBodyFormat } from \"./trace-compact.js\";\nimport type { CfLiveTraceTarget, LiveTraceEvent } from \"./types.js\";\n\nconst SAPTOOLS_DIR_NAME = \".saptools\";\nconst CF_LIVE_TRACE_DIR_NAME = \"cf-live-trace\";\nconst SESSIONS_DIR_NAME = \"sessions\";\nconst EVENTS_DIR_NAME = \"events\";\nconst MANIFEST_FILE_NAME = \"manifest.json\";\nconst TRACE_TTL_MS = 2 * 60 * 60 * 1000;\nconst MAX_TARGET_SLUG_BYTES = 160;\nconst SESSION_ID_PATTERN = /^s(?:[0-9a-f]{8}|[0-9a-f]{16})$/;\nconst REQUEST_ID_PATTERN = /^r(?:[0-9a-f]{8}|[0-9a-f]{16})$/;\n\nexport interface TraceTargetIdentity {\n readonly region?: string;\n readonly apiEndpoint?: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n readonly instance: string;\n}\n\nexport interface TraceSession {\n readonly sessionId: string;\n readonly createdAt: string;\n readonly target: TraceTargetIdentity;\n readonly directory: string;\n readonly eventsDirectory: string;\n readonly manifestPath: string;\n}\n\nexport interface StoredTraceEvent {\n readonly version: 1;\n readonly sessionId: string;\n readonly requestId: string;\n readonly createdAt: string;\n readonly expiresAt: string;\n readonly target: TraceTargetIdentity;\n readonly requestBodyFormat: TraceBodyFormat;\n readonly responseBodyFormat: TraceBodyFormat;\n readonly event: LiveTraceEvent;\n}\n\nexport interface StoredTraceEventFile extends StoredTraceEvent {\n readonly backupPath: string;\n}\n\nexport interface TraceSessionSummary {\n readonly sessionId: string;\n readonly createdAt: string;\n readonly target: TraceTargetIdentity;\n readonly eventCount: number;\n readonly directory: string;\n}\n\nexport interface CreateTraceSessionInput {\n readonly target: CfLiveTraceTarget;\n}\n\nexport interface TraceStoreOptions {\n readonly saptoolsRoot?: string;\n readonly now?: () => Date;\n readonly sessionId?: string;\n readonly requestId?: () => string;\n}\n\nexport type TraceEventVisitor = (\n record: StoredTraceEventFile,\n) => boolean | Promise<boolean>;\n\ninterface StoredTraceSessionManifest {\n readonly version: 1;\n readonly sessionId: string;\n readonly createdAt: string;\n readonly target: TraceTargetIdentity;\n}\n\nexport function traceSessionsRoot(saptoolsRoot?: string): string {\n return join(saptoolsRoot ?? join(homedir(), SAPTOOLS_DIR_NAME), CF_LIVE_TRACE_DIR_NAME, SESSIONS_DIR_NAME);\n}\n\nexport async function createTraceSession(\n input: CreateTraceSessionInput,\n options: TraceStoreOptions = {},\n): Promise<TraceSession> {\n await pruneTraceSessions(options);\n const sessionId = resolveSessionId(options.sessionId);\n const createdAt = (options.now?.() ?? new Date()).toISOString();\n const target = toTargetIdentity(input.target);\n const directory = sessionDirectory(sessionId, options.saptoolsRoot);\n const eventsDirectory = join(directory, EVENTS_DIR_NAME);\n const manifestPath = join(directory, MANIFEST_FILE_NAME);\n await mkdir(eventsDirectory, { recursive: true, mode: 0o700 });\n await writeJsonFile(manifestPath, createManifest(sessionId, createdAt, target));\n return { sessionId, createdAt, target, directory, eventsDirectory, manifestPath };\n}\n\nexport async function writeTraceEvent(\n session: TraceSession,\n event: LiveTraceEvent,\n options: TraceStoreOptions = {},\n): Promise<StoredTraceEventFile> {\n const now = options.now?.() ?? new Date();\n const requestId = resolveRequestId(options.requestId?.());\n await ensureSessionManifest(session);\n const record: StoredTraceEvent = {\n version: 1,\n sessionId: session.sessionId,\n requestId,\n createdAt: now.toISOString(),\n expiresAt: new Date(now.getTime() + TRACE_TTL_MS).toISOString(),\n target: session.target,\n requestBodyFormat: detectBodyFormat(event.requestBodyPreview, event.requestHeaders),\n responseBodyFormat: detectBodyFormat(event.responseBodyPreview, event.responseHeaders),\n event,\n };\n const backupPath = join(session.eventsDirectory, eventFileName(record, now));\n await mkdir(session.eventsDirectory, { recursive: true, mode: 0o700 });\n await writeJsonFile(backupPath, record);\n return { ...record, backupPath };\n}\n\nexport async function readTraceEvent(\n sessionId: string,\n requestId: string,\n options: TraceStoreOptions = {},\n): Promise<StoredTraceEventFile> {\n const resolvedSessionId = resolveSessionId(sessionId);\n const resolvedRequestId = resolveRequestId(requestId);\n const entries = await listEventFilePaths(resolvedSessionId, options.saptoolsRoot);\n const candidates = entries.filter((path) => path.includes(`-${resolvedRequestId}-`));\n for (const path of candidates) {\n const record = await readStoredTraceEvent(path, resolvedSessionId);\n if (record === undefined || isExpired(record, options)) {\n await rm(path, { force: true });\n continue;\n }\n if (record.requestId === resolvedRequestId) {\n return record;\n }\n }\n throw new Error(\"Saved trace request not found or expired\");\n}\n\nexport async function listTraceEvents(\n sessionId: string,\n options: TraceStoreOptions = {},\n): Promise<readonly StoredTraceEventFile[]> {\n const records: StoredTraceEventFile[] = [];\n await visitTraceEvents(sessionId, (record) => {\n records.push(record);\n return true;\n }, options);\n return records;\n}\n\nexport async function visitTraceEvents(\n sessionId: string,\n visitor: TraceEventVisitor,\n options: TraceStoreOptions = {},\n): Promise<void> {\n const resolvedSessionId = resolveSessionId(sessionId);\n const entries = await listEventFilePaths(resolvedSessionId, options.saptoolsRoot);\n for (const path of entries) {\n const record = await readStoredTraceEvent(path, resolvedSessionId);\n if (record === undefined || isExpired(record, options)) {\n await rm(path, { force: true });\n continue;\n }\n if (!await visitor(record)) {\n return;\n }\n }\n}\n\nexport async function listTraceSessions(options: TraceStoreOptions = {}): Promise<readonly TraceSessionSummary[]> {\n await pruneTraceSessions(options);\n const sessionIds = await listSessionIds(options.saptoolsRoot);\n const summaries = await Promise.all(sessionIds.map(async (sessionId) => await readSessionSummary(sessionId, options)));\n return summaries\n .filter((summary): summary is TraceSessionSummary => summary !== undefined)\n .sort((left, right) => left.createdAt.localeCompare(right.createdAt));\n}\n\nexport async function pruneTraceSessions(options: TraceStoreOptions = {}): Promise<number> {\n const sessionIds = await listSessionIds(options.saptoolsRoot);\n const now = (options.now?.() ?? new Date()).getTime();\n let removed = 0;\n for (const sessionId of sessionIds) {\n removed += await pruneSession(sessionId, now, options.saptoolsRoot);\n }\n return removed;\n}\n\nfunction toTargetIdentity(target: CfLiveTraceTarget): TraceTargetIdentity {\n return {\n ...(target.region === undefined ? {} : { region: target.region }),\n ...(target.apiEndpoint === undefined ? {} : { apiEndpoint: target.apiEndpoint }),\n org: target.org,\n space: target.space,\n app: target.app,\n instance: String(target.instanceIndex ?? 0),\n };\n}\n\nfunction createManifest(\n sessionId: string,\n createdAt: string,\n target: TraceTargetIdentity,\n): StoredTraceSessionManifest {\n return { version: 1, sessionId, createdAt, target };\n}\n\nasync function ensureSessionManifest(session: TraceSession): Promise<void> {\n try {\n await access(session.manifestPath);\n return;\n } catch (error) {\n if (!isNodeError(error, \"ENOENT\")) {\n throw error;\n }\n }\n await mkdir(session.eventsDirectory, { recursive: true, mode: 0o700 });\n await writeJsonFile(\n session.manifestPath,\n createManifest(session.sessionId, session.createdAt, session.target),\n );\n}\n\nfunction isExpired(record: StoredTraceEvent, options: TraceStoreOptions): boolean {\n const now = (options.now?.() ?? new Date()).getTime();\n return Date.parse(record.expiresAt) <= now;\n}\n\nasync function readSessionSummary(\n sessionId: string,\n options: TraceStoreOptions,\n): Promise<TraceSessionSummary | undefined> {\n const manifest = await readStoredManifest(manifestPath(sessionId, options.saptoolsRoot));\n if (manifest?.sessionId !== sessionId) {\n return undefined;\n }\n const eventCount = (await listEventFilePaths(sessionId, options.saptoolsRoot)).length;\n return {\n sessionId,\n createdAt: manifest.createdAt,\n target: manifest.target,\n eventCount,\n directory: sessionDirectory(sessionId, options.saptoolsRoot),\n };\n}\n\nasync function pruneSession(sessionId: string, now: number, saptoolsRoot?: string): Promise<number> {\n const manifest = await readStoredManifest(manifestPath(sessionId, saptoolsRoot));\n const eventPaths = await listEventFilePaths(sessionId, saptoolsRoot);\n let removed = 0;\n let remaining = 0;\n for (const path of eventPaths) {\n const expiresAt = eventPathExpiresAt(path) ?? await storedEventExpiresAt(path);\n if (expiresAt === undefined || expiresAt <= now) {\n await rm(path, { force: true });\n removed += 1;\n } else {\n remaining += 1;\n }\n }\n if (remaining === 0 && isManifestExpiredOrMissing(manifest, now)) {\n await rm(sessionDirectory(sessionId, saptoolsRoot), { recursive: true, force: true });\n }\n return removed;\n}\n\nasync function storedEventExpiresAt(path: string): Promise<number | undefined> {\n const record = await readStoredTraceEvent(path);\n return record === undefined ? undefined : Date.parse(record.expiresAt);\n}\n\nfunction isManifestExpiredOrMissing(manifest: StoredTraceSessionManifest | undefined, now: number): boolean {\n if (manifest === undefined) {\n return true;\n }\n return Date.parse(manifest.createdAt) + TRACE_TTL_MS <= now;\n}\n\nasync function listSessionIds(saptoolsRoot?: string): Promise<readonly string[]> {\n try {\n const entries = await readdir(traceSessionsRoot(saptoolsRoot), { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory() && SESSION_ID_PATTERN.test(entry.name))\n .map((entry) => entry.name);\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return [];\n }\n throw error;\n }\n}\n\nasync function listEventFilePaths(sessionId: string, saptoolsRoot?: string): Promise<readonly string[]> {\n try {\n const directory = eventsDirectory(sessionId, saptoolsRoot);\n const entries = await readdir(directory, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".json\"))\n .map((entry) => join(directory, entry.name))\n .sort(compareEventPaths);\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return [];\n }\n throw error;\n }\n}\n\nfunction compareEventPaths(left: string, right: string): number {\n const leftTimestamp = eventPathTimestamp(left);\n const rightTimestamp = eventPathTimestamp(right);\n return leftTimestamp.localeCompare(rightTimestamp) || left.localeCompare(right);\n}\n\nfunction eventPathTimestamp(path: string): string {\n return /-(\\d{8}T\\d{9}Z)\\.json$/.exec(path)?.[1] ?? \"\";\n}\n\nfunction eventPathExpiresAt(path: string): number | undefined {\n const compact = eventPathTimestamp(path);\n if (compact.length === 0) {\n return undefined;\n }\n const iso = compact.replace(\n /^(\\d{4})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})(\\d{2})(\\d{3})Z$/,\n \"$1-$2-$3T$4:$5:$6.$7Z\",\n );\n const createdAt = Date.parse(iso);\n return Number.isNaN(createdAt) ? undefined : createdAt + TRACE_TTL_MS;\n}\n\nasync function readStoredManifest(path: string): Promise<StoredTraceSessionManifest | undefined> {\n const parsed = await readJsonFile(path);\n return parsed !== undefined && isStoredManifest(parsed) ? parsed : undefined;\n}\n\nasync function readStoredTraceEvent(\n path: string,\n expectedSessionId?: string,\n): Promise<StoredTraceEventFile | undefined> {\n const parsed = await readJsonFile(path);\n if (parsed === undefined || !isStoredTraceEvent(parsed)) {\n return undefined;\n }\n if (expectedSessionId !== undefined && parsed.sessionId !== expectedSessionId) {\n return undefined;\n }\n return { ...parsed, backupPath: path };\n}\n\nasync function readJsonFile(path: string): Promise<unknown> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (error) {\n if (isNodeError(error, \"ENOENT\")) {\n return undefined;\n }\n throw error;\n }\n try {\n return JSON.parse(raw) as unknown;\n } catch (error) {\n if (!(error instanceof SyntaxError)) {\n throw error;\n }\n return undefined;\n }\n}\n\nasync function writeJsonFile(path: string, value: unknown): Promise<void> {\n const temporaryPath = `${path}.tmp-${process.pid.toString()}-${randomHex(4)}`;\n let renamed = false;\n try {\n await writeFile(temporaryPath, `${JSON.stringify(value, null, 2)}\\n`, {\n encoding: \"utf8\",\n mode: 0o600,\n });\n await rename(temporaryPath, path);\n renamed = true;\n } finally {\n if (!renamed) {\n await rm(temporaryPath, { force: true });\n }\n }\n}\n\nfunction eventFileName(record: StoredTraceEvent, now: Date): string {\n const parts = [\n targetSlug(record.target),\n record.sessionId,\n record.requestId,\n fileTimestamp(now),\n ].join(\"-\");\n return `${parts}.json`;\n}\n\nfunction targetSlug(target: TraceTargetIdentity): string {\n const regionOrApi = target.region ?? target.apiEndpoint ?? \"api\";\n const fullSlug = [regionOrApi, target.org, target.space, target.app]\n .map(sanitizePathPart)\n .join(\"-\");\n if (Buffer.byteLength(fullSlug) <= MAX_TARGET_SLUG_BYTES) {\n return fullSlug;\n }\n const hash = createHash(\"sha256\").update(fullSlug).digest(\"hex\").slice(0, 12);\n const prefix = fullSlug.slice(0, MAX_TARGET_SLUG_BYTES - hash.length - 1).replace(/(?<!-)-+$/, \"\");\n return `${prefix}-${hash}`;\n}\n\nfunction sanitizePathPart(value: string): string {\n const sanitized = value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, \"-\").replace(/^-+|(?<!-)-+$/g, \"\");\n return sanitized.length === 0 ? \"unknown\" : sanitized;\n}\n\nfunction fileTimestamp(now: Date): string {\n return now.toISOString().replaceAll(\"-\", \"\").replaceAll(\":\", \"\").replace(\".\", \"\");\n}\n\nfunction sessionDirectory(sessionId: string, saptoolsRoot?: string): string {\n return join(traceSessionsRoot(saptoolsRoot), sessionId);\n}\n\nfunction eventsDirectory(sessionId: string, saptoolsRoot?: string): string {\n return join(sessionDirectory(sessionId, saptoolsRoot), EVENTS_DIR_NAME);\n}\n\nfunction manifestPath(sessionId: string, saptoolsRoot?: string): string {\n return join(sessionDirectory(sessionId, saptoolsRoot), MANIFEST_FILE_NAME);\n}\n\nfunction resolveSessionId(value: string | undefined): string {\n const sessionId = value ?? `s${randomHex(8)}`;\n if (!SESSION_ID_PATTERN.test(sessionId)) {\n throw new Error(\"Invalid trace session id\");\n }\n return sessionId;\n}\n\nfunction resolveRequestId(value: string | undefined): string {\n const requestId = value ?? `r${randomHex(8)}`;\n if (!REQUEST_ID_PATTERN.test(requestId)) {\n throw new Error(\"Invalid trace request id\");\n }\n return requestId;\n}\n\nfunction randomHex(bytes: number): string {\n return randomBytes(bytes).toString(\"hex\");\n}\n\nfunction isStoredManifest(value: unknown): value is StoredTraceSessionManifest {\n return (\n isRecord(value) &&\n value[\"version\"] === 1 &&\n isSessionId(value[\"sessionId\"]) &&\n isIsoTimestamp(value[\"createdAt\"]) &&\n isTraceTargetIdentity(value[\"target\"])\n );\n}\n\nfunction isStoredTraceEvent(value: unknown): value is StoredTraceEvent {\n return (\n isRecord(value) &&\n value[\"version\"] === 1 &&\n isStoredEventMetadata(value) &&\n isTraceTargetIdentity(value[\"target\"]) &&\n isTraceBodyFormat(value[\"requestBodyFormat\"]) &&\n isTraceBodyFormat(value[\"responseBodyFormat\"]) &&\n isLiveTraceEvent(value[\"event\"])\n );\n}\n\nfunction isStoredEventMetadata(value: Record<string, unknown>): boolean {\n return (\n isSessionId(value[\"sessionId\"]) &&\n isRequestId(value[\"requestId\"]) &&\n isIsoTimestamp(value[\"createdAt\"]) &&\n isIsoTimestamp(value[\"expiresAt\"])\n );\n}\n\nfunction isTraceTargetIdentity(value: unknown): value is TraceTargetIdentity {\n return (\n isRecord(value) &&\n optionalString(value[\"region\"]) &&\n optionalString(value[\"apiEndpoint\"]) &&\n typeof value[\"org\"] === \"string\" &&\n typeof value[\"space\"] === \"string\" &&\n typeof value[\"app\"] === \"string\" &&\n typeof value[\"instance\"] === \"string\"\n );\n}\n\nfunction isLiveTraceEvent(value: unknown): value is LiveTraceEvent {\n return (\n isRecord(value) &&\n hasLiveTraceStrings(value) &&\n hasLiveTraceMetrics(value) &&\n isStringRecord(value[\"requestHeaders\"]) &&\n isStringRecord(value[\"responseHeaders\"]) &&\n typeof value[\"requestBodyTruncated\"] === \"boolean\" &&\n typeof value[\"responseBodyTruncated\"] === \"boolean\" &&\n value[\"source\"] === \"runtime-http\" &&\n optionalNullableString(value[\"correlationId\"])\n );\n}\n\nfunction hasLiveTraceStrings(value: Record<string, unknown>): boolean {\n const fields = [\n \"id\",\n \"appId\",\n \"instance\",\n \"method\",\n \"path\",\n \"url\",\n \"normalizedUrl\",\n \"requestBodyPreview\",\n \"responseBodyPreview\",\n \"traceId\",\n ];\n return isIsoTimestamp(value[\"timestamp\"]) && fields.every((field) => typeof value[field] === \"string\");\n}\n\nfunction hasLiveTraceMetrics(value: Record<string, unknown>): boolean {\n return (\n isNullableFiniteNumber(value[\"status\"]) &&\n isNullableNonNegativeNumber(value[\"durationMs\"]) &&\n isNonNegativeFiniteNumber(value[\"requestBytes\"]) &&\n isNonNegativeFiniteNumber(value[\"responseBytes\"]) &&\n isNonNegativeFiniteNumber(value[\"droppedBeforeEvent\"])\n );\n}\n\nfunction isTraceBodyFormat(value: unknown): value is TraceBodyFormat {\n return (\n value === \"empty\" ||\n value === \"json\" ||\n value === \"xml\" ||\n value === \"html\" ||\n value === \"form\" ||\n value === \"text\" ||\n value === \"binary\" ||\n value === \"unknown\"\n );\n}\n\nfunction optionalString(value: unknown): boolean {\n return value === undefined || typeof value === \"string\";\n}\n\nfunction optionalNullableString(value: unknown): boolean {\n return value === null || typeof value === \"string\";\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return isRecord(value) && Object.values(value).every((entry) => typeof entry === \"string\");\n}\n\nfunction isSessionId(value: unknown): value is string {\n return typeof value === \"string\" && SESSION_ID_PATTERN.test(value);\n}\n\nfunction isRequestId(value: unknown): value is string {\n return typeof value === \"string\" && REQUEST_ID_PATTERN.test(value);\n}\n\nfunction isIsoTimestamp(value: unknown): value is string {\n if (typeof value !== \"string\") {\n return false;\n }\n const parsed = new Date(value);\n return !Number.isNaN(parsed.getTime()) && parsed.toISOString() === value;\n}\n\nfunction isNullableFiniteNumber(value: unknown): boolean {\n return value === null || isFiniteNumber(value);\n}\n\nfunction isNullableNonNegativeNumber(value: unknown): boolean {\n return value === null || isNonNegativeFiniteNumber(value);\n}\n\nfunction isNonNegativeFiniteNumber(value: unknown): boolean {\n return isFiniteNumber(value) && value >= 0;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return isRecord(error) && error[\"code\"] === code;\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 | Promise<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 MAX_DRAIN_EVALUATE_TIMEOUT_MS = 60_000;\nconst DRAIN_BODY_BUDGET_BYTES = 8 * 1024 * 1024;\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 summaryEvents: LiveTraceEvent[] = [];\n private consecutiveDrainTimeouts = 0;\n private drainTask: Promise<void> | undefined;\n private inspectorClient: InspectorRuntimeClient | undefined;\n private pollTimer: NodeJS.Timeout | undefined;\n private pendingDrainAcknowledgement: string | null = null;\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 this.pendingDrainAcknowledgement = null;\n this.summaryEvents.splice(0);\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 this.startDrain(maxBodyBytes);\n }, DRAIN_INTERVAL_MS);\n }\n\n private startDrain(maxBodyBytes: number): void {\n if (this.drainTask !== undefined || this.inspectorClient === undefined || this.state !== \"streaming\") {\n return;\n }\n const task = this.drainTraceEvents(maxBodyBytes);\n this.drainTask = task;\n void task.then(\n () => {\n this.clearDrainTask(task);\n },\n () => {\n this.clearDrainTask(task);\n },\n );\n }\n\n private clearDrainTask(task: Promise<void>): void {\n if (this.drainTask === task) {\n this.drainTask = undefined;\n }\n }\n\n private async drainTraceEvents(maxBodyBytes: number): Promise<void> {\n const batchSize = resolveDrainBatchSize(maxBodyBytes);\n try {\n const payload = await this.requireInspector().evaluate(\n buildDrainExpression(\n batchSize,\n resolveDrainTransportBodyLimit(maxBodyBytes),\n this.pendingDrainAcknowledgement,\n ),\n resolveDrainEvaluateTimeout(maxBodyBytes, batchSize),\n );\n this.consecutiveDrainTimeouts = 0;\n try {\n await this.publishDrainedEvents(payload, maxBodyBytes);\n } catch (error) {\n await this.handleEventHandlerFailure(error);\n }\n } catch (error) {\n await this.handleDrainFailure(error);\n }\n }\n\n private async publishDrainedEvents(payload: unknown, maxBodyBytes: number): Promise<void> {\n const drained = parseDrainResult(payload, { appId: this.options.target.app, maxBodyBytes });\n if (drained.events.length > 0) {\n await this.options.onEvents?.(drained.events);\n this.publishSummary(drained.events);\n }\n this.pendingDrainAcknowledgement = drained.drainId;\n }\n\n private publishSummary(events: readonly LiveTraceEvent[]): void {\n if (this.options.onSummary === undefined) {\n return;\n }\n this.summaryEvents.push(...events.map(toSummaryEvent));\n this.summaryEvents.splice(0, Math.max(0, this.summaryEvents.length - RUNTIME_QUEUE_SIZE));\n this.options.onSummary(buildUrlSummaries(this.summaryEvents));\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, false);\n this.postState(\"error\", \"Runtime HTTP trace connection was lost.\", false, true);\n }\n\n private async handleEventHandlerFailure(error: unknown): Promise<void> {\n this.log(`Live Trace event handler failed for ${this.options.target.app}: ${formatError(error)}`);\n await this.stopRuntimeTrace(false, false);\n this.postState(\"error\", \"Trace event handler failed.\", false, true);\n }\n\n private async stopRuntimeTrace(\n uninstallRuntimeHook: boolean,\n waitForDrain = true,\n ): Promise<boolean> {\n this.stopPolling();\n if (waitForDrain) {\n await this.drainTask;\n }\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 const maxBodyBytes = options.maxBodyBytes ?? 4096;\n if (!Number.isSafeInteger(maxBodyBytes) || maxBodyBytes <= 0) {\n throw new Error(\"maxBodyBytes must be a positive safe integer.\");\n }\n const runtimeQueueSize = options.runtimeQueueSize ?? RUNTIME_QUEUE_SIZE;\n if (!Number.isSafeInteger(runtimeQueueSize) || runtimeQueueSize <= 0) {\n throw new Error(\"runtimeQueueSize must be a positive safe integer.\");\n }\n return {\n captureHeaders: options.captureHeaders ?? true,\n captureRequestBody: options.captureRequestBody ?? true,\n captureResponseBody: options.captureResponseBody ?? true,\n maxBodyBytes,\n runtimeQueueSize,\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 ? maxBodyBytes : 1;\n}\n\nfunction resolveDrainBatchSize(maxBodyBytes: number): number {\n const perEventBytes = Math.max(1, maxBodyBytes * 2);\n return Math.max(1, Math.min(DRAIN_BATCH_SIZE, Math.floor(DRAIN_BODY_BUDGET_BYTES / perEventBytes)));\n}\n\nfunction resolveDrainEvaluateTimeout(maxBodyBytes: number, batchSize: number): number {\n const estimatedBytes = Math.min(Number.MAX_SAFE_INTEGER, maxBodyBytes * 2 * batchSize);\n const extraMegabytes = Math.ceil(Math.max(0, estimatedBytes - 1_000_000) / 1_000_000);\n return Math.min(MAX_DRAIN_EVALUATE_TIMEOUT_MS, DRAIN_EVALUATE_TIMEOUT_MS + extraMegabytes * 5_000);\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\nfunction toSummaryEvent(event: LiveTraceEvent): LiveTraceEvent {\n return {\n ...event,\n requestHeaders: {},\n responseHeaders: {},\n requestBodyPreview: \"\",\n responseBodyPreview: \"\",\n };\n}\n"],"mappings":"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","names":["Buffer","isRecord","eventsDirectory","manifestPath","isRecord","rm","join","isRecord"]}
|