capacitor-gleap-plugin 18.0.0 → 19.0.0

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.
Files changed (43) hide show
  1. package/CapacitorGleapPlugin.podspec +7 -2
  2. package/Package.swift +31 -0
  3. package/README.md +307 -761
  4. package/android/build.gradle +1 -1
  5. package/android/src/main/java/io/gleapplugins/capacitor/GleapPlugin.java +228 -37
  6. package/dist/docs.json +323 -3907
  7. package/dist/esm/definitions.d.ts +168 -3
  8. package/dist/esm/definitions.js.map +1 -1
  9. package/dist/esm/index.js +9 -1
  10. package/dist/esm/index.js.map +1 -1
  11. package/dist/esm/logs/body.d.ts +58 -0
  12. package/dist/esm/logs/body.js +303 -0
  13. package/dist/esm/logs/body.js.map +1 -0
  14. package/dist/esm/logs/consoleCapture.d.ts +29 -0
  15. package/dist/esm/logs/consoleCapture.js +189 -0
  16. package/dist/esm/logs/consoleCapture.js.map +1 -0
  17. package/dist/esm/logs/format.d.ts +16 -0
  18. package/dist/esm/logs/format.js +394 -0
  19. package/dist/esm/logs/format.js.map +1 -0
  20. package/dist/esm/logs/networkCapture.d.ts +65 -0
  21. package/dist/esm/logs/networkCapture.js +654 -0
  22. package/dist/esm/logs/networkCapture.js.map +1 -0
  23. package/dist/esm/logs/redaction.d.ts +54 -0
  24. package/dist/esm/logs/redaction.js +388 -0
  25. package/dist/esm/logs/redaction.js.map +1 -0
  26. package/dist/esm/logs/webViewLogs.d.ts +70 -0
  27. package/dist/esm/logs/webViewLogs.js +297 -0
  28. package/dist/esm/logs/webViewLogs.js.map +1 -0
  29. package/dist/esm/logs/zone.d.ts +5 -0
  30. package/dist/esm/logs/zone.js +15 -0
  31. package/dist/esm/logs/zone.js.map +1 -0
  32. package/dist/esm/web.d.ts +47 -2
  33. package/dist/esm/web.js +43 -0
  34. package/dist/esm/web.js.map +1 -1
  35. package/dist/plugin.cjs.js +2263 -1
  36. package/dist/plugin.cjs.js.map +1 -1
  37. package/dist/plugin.js +2263 -1
  38. package/dist/plugin.js.map +1 -1
  39. package/ios/{Plugin → Sources/GleapPlugin}/GleapPlugin.swift +222 -12
  40. package/package.json +27 -6
  41. package/ios/Plugin/GleapPlugin.h +0 -10
  42. package/ios/Plugin/GleapPlugin.m +0 -66
  43. package/ios/Plugin/Info.plist +0 -24
@@ -0,0 +1 @@
1
+ {"version":3,"file":"networkCapture.js","sourceRoot":"","sources":["../../../src/logs/networkCapture.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GleapNetworkLogEntry } from '../definitions';\n\nimport {\n BINARY_BODY_OMITTED,\n BODY_NOT_CAPTURED,\n BODY_PENDING,\n MAX_BODY_SIZE,\n STREAMING_BODY_OMITTED,\n bytesToBodyText,\n capBodyText,\n captureRequestBody,\n classifyContentType,\n isBlob,\n isUrlSearchParams,\n markerForKind,\n readBlobHead,\n readStreamHead,\n stringifyJsonHead,\n toBytes,\n} from './body';\nimport { DEFAULT_NETWORK_LOG_BLACKLIST } from './redaction';\nimport { runOutsideZone } from './zone';\n\nexport const MAX_NETWORK_ENTRIES = 30;\n\ntype HeaderMap = { [name: string]: string };\ntype AnyFunction = (...args: unknown[]) => unknown;\n\ninterface NetworkRecord {\n id: number;\n /** Bumped on every change, so the pusher can reuse the redacted copy of unchanged entries. */\n version: number;\n startedAt: number;\n entry: GleapNetworkLogEntry;\n}\n\nexport interface NetworkLogSnapshot {\n id: number;\n version: number;\n entry: GleapNetworkLogEntry;\n}\n\ninterface XhrState {\n method: string;\n url: string;\n headers: HeaderMap;\n record: NetworkRecord | null;\n headersAt: number | null;\n failure: 'abort' | 'timeout' | 'error' | null;\n loaded: boolean;\n}\n\nconst now = (): number =>\n typeof performance !== 'undefined' && typeof performance.now === 'function' ? performance.now() : Date.now();\n\n/**\n * Records fetch and XMLHttpRequest calls made inside the WebView. The hooks never alter or delay the\n * request: they only read what the app passes in and what comes back, and every hook is guarded so\n * a logging failure cannot break the app's networking.\n */\nexport class NetworkCapture {\n private records: NetworkRecord[] = [];\n private nextId = 1;\n private active = false;\n private isInstalled = false;\n private xhrStates = new WeakMap<object, XhrState>();\n private xhrsWithListeners = new WeakSet<object>();\n\n constructor(\n private readonly win: Window,\n private readonly onChange: () => void,\n ) {}\n\n /** Installs the hooks inactive: nothing is recorded until setActive(true). */\n install(): void {\n if (this.isInstalled) {\n return;\n }\n this.isInstalled = true;\n try {\n this.patchFetch();\n } catch (e) {\n // Ignore.\n }\n try {\n this.patchXhr();\n } catch (e) {\n // Ignore.\n }\n }\n\n /** Inactive: the hooks stay in place but only call through, and the buffer is dropped. */\n setActive(active: boolean): void {\n this.active = active;\n if (!active) {\n this.records = [];\n }\n }\n\n getSnapshots(): NetworkLogSnapshot[] {\n return this.records.map((record) => ({\n id: record.id,\n version: record.version,\n entry: record.entry,\n }));\n }\n\n // ---------------------------------------------------------------- fetch\n\n private patchFetch(): void {\n const win = this.win as unknown as { fetch?: AnyFunction };\n const originalFetch = win.fetch;\n if (typeof originalFetch !== 'function') {\n return;\n }\n const capture = this;\n win.fetch = function gleapFetch(this: unknown): unknown {\n // eslint-disable-next-line prefer-rest-params\n const args = arguments;\n let record: NetworkRecord | null = null;\n if (capture.active) {\n try {\n record = capture.startFetch(args[0], args[1]);\n } catch (e) {\n record = null;\n }\n }\n let result: unknown;\n try {\n result = originalFetch.apply(this, args as unknown as unknown[]);\n } catch (error) {\n if (record) {\n capture.fail(record, error);\n }\n throw error;\n }\n const promise = result as Promise<Response> | null;\n if (!record || !promise || typeof promise.then !== 'function') {\n return result;\n }\n const tracked = record;\n return promise.then(\n (response) => {\n capture.completeFetch(tracked, response);\n return response;\n },\n (error) => {\n capture.fail(tracked, error);\n throw error;\n },\n );\n };\n }\n\n private startFetch(input: unknown, init: unknown): NetworkRecord | null {\n const url = this.resolveUrl(isRequest(input) ? input.url : isUrl(input) ? input.href : input);\n if (!this.shouldCapture(url)) {\n return null;\n }\n const request = isRequest(input) ? input : null;\n const options = init && typeof init === 'object' ? (init as RequestInit) : undefined;\n const method = String(options?.method || request?.method || 'GET').toUpperCase();\n const headers = normalizeHeaders(\n options?.headers !== undefined ? options.headers : request ? request.headers : undefined,\n );\n\n let payload: string | Promise<string> = '';\n if (options?.body !== undefined && options?.body !== null) {\n payload = this.requestPayload(options.body, headers);\n } else if (request && method !== 'GET' && method !== 'HEAD') {\n payload = this.requestObjectPayload(request, headers);\n }\n return this.createRecord(method, url, headers, payload);\n }\n\n /** The body of a Request object: read from a clone (made before fetch consumes it), head only. */\n private requestObjectPayload(request: Request, headers: HeaderMap): string | Promise<string> {\n const kind = classifyContentType(headers['content-type']);\n const marker = markerForKind(kind);\n if (marker) {\n return marker;\n }\n if (typeof Request === 'undefined' || !('body' in Request.prototype)) {\n return BODY_NOT_CAPTURED;\n }\n if (request.body === null) {\n return '';\n }\n let copy: Request;\n try {\n copy = request.clone();\n } catch (e) {\n return BODY_NOT_CAPTURED;\n }\n const stream = copy.body;\n if (!stream || typeof stream.getReader !== 'function') {\n return BODY_NOT_CAPTURED;\n }\n return runOutsideZone(() =>\n readStreamHead(stream).then(\n ({ bytes, complete }) => bytesToBodyText(bytes, kind, complete, null),\n () => BODY_NOT_CAPTURED,\n ),\n );\n }\n\n private completeFetch(record: NetworkRecord, response: Response): void {\n try {\n const headers = normalizeHeaders(response.headers);\n this.update(record, (entry) => {\n entry.duration = Math.round(now() - record.startedAt);\n entry.success = true;\n entry.response = {\n status: response.status,\n statusText: response.statusText || '',\n headers,\n responseText: BODY_PENDING,\n };\n });\n this.setResponseText(record, this.fetchResponseBody(response, headers));\n } catch (e) {\n // Ignore.\n }\n }\n\n /**\n * Streaming and binary responses are never cloned. Text responses are cloned synchronously (before\n * the app sees the response) and only the head of the clone is read, then the clone is cancelled.\n */\n private fetchResponseBody(response: Response, headers: HeaderMap): string | Promise<string> {\n const kind = classifyContentType(headers['content-type']);\n const marker = markerForKind(kind);\n if (marker) {\n return marker;\n }\n if (response.type === 'opaque' || response.type === 'opaqueredirect') {\n return BODY_NOT_CAPTURED;\n }\n const body = response.body;\n if (body === null) {\n return '';\n }\n if (!body || typeof body.getReader !== 'function' || typeof response.clone !== 'function') {\n return BODY_NOT_CAPTURED;\n }\n let copy: Response;\n try {\n copy = response.clone();\n } catch (e) {\n return BODY_NOT_CAPTURED;\n }\n const stream = copy.body;\n if (!stream) {\n return '';\n }\n const totalBytes = identityContentLength(headers);\n return runOutsideZone(() =>\n readStreamHead(stream).then(\n ({ bytes, complete }) => bytesToBodyText(bytes, kind, complete, complete ? null : totalBytes),\n () => BODY_NOT_CAPTURED,\n ),\n );\n }\n\n // ------------------------------------------------------------------ XHR\n\n private patchXhr(): void {\n const win = this.win as unknown as {\n XMLHttpRequest?: unknown;\n CapacitorWebXMLHttpRequest?: { fullObject?: unknown };\n };\n const Xhr = win.XMLHttpRequest as (AnyFunction & { prototype?: { [name: string]: unknown } }) | undefined;\n if (typeof Xhr !== 'function' || !Xhr || !Xhr.prototype) {\n return;\n }\n const capacitorXhr = win.CapacitorWebXMLHttpRequest;\n if (capacitorXhr?.fullObject && Xhr !== capacitorXhr.fullObject) {\n // CapacitorHttp replaced the constructor and re-assigns the prototype methods on every\n // construction, so the methods are hooked per instance instead.\n this.wrapXhrConstructor(Xhr);\n return;\n }\n const proto = Xhr.prototype;\n const originals: { [name: string]: unknown } = {\n open: proto.open,\n send: proto.send,\n setRequestHeader: proto.setRequestHeader,\n };\n if (\n typeof originals.open !== 'function' ||\n typeof originals.send !== 'function' ||\n typeof originals.setRequestHeader !== 'function'\n ) {\n return;\n }\n this.hookXhrMethods(proto, (_xhr, name) => originals[name] as AnyFunction);\n }\n\n private wrapXhrConstructor(Factory: AnyFunction): void {\n const capture = this;\n const Wrapped = function GleapXMLHttpRequest(): unknown {\n const xhr = new (Factory as unknown as new () => object)();\n try {\n capture.hookXhrMethods(\n xhr as { [name: string]: unknown },\n (instance, name) => (Object.getPrototypeOf(instance) as { [name: string]: unknown })[name] as AnyFunction,\n );\n } catch (e) {\n // Ignore.\n }\n return xhr;\n } as unknown as { [name: string]: unknown; prototype: unknown };\n try {\n Object.assign(Wrapped, Factory);\n } catch (e) {\n // Ignore.\n }\n Wrapped.prototype = (Factory as unknown as { prototype: unknown }).prototype;\n (this.win as unknown as { XMLHttpRequest: unknown }).XMLHttpRequest = Wrapped;\n }\n\n private hookXhrMethods(\n target: { [name: string]: unknown },\n original: (xhr: object, name: string) => AnyFunction,\n ): void {\n const capture = this;\n target.open = function (this: object): unknown {\n // eslint-disable-next-line prefer-rest-params\n const args = arguments;\n try {\n capture.onXhrOpen(this, args[0], args[1]);\n } catch (e) {\n // Ignore.\n }\n return original(this, 'open').apply(this, args as unknown as unknown[]);\n };\n target.setRequestHeader = function (this: object): unknown {\n // eslint-disable-next-line prefer-rest-params\n const args = arguments;\n try {\n capture.onXhrHeader(this, args[0], args[1]);\n } catch (e) {\n // Ignore.\n }\n return original(this, 'setRequestHeader').apply(this, args as unknown as unknown[]);\n };\n target.send = function (this: object): unknown {\n // eslint-disable-next-line prefer-rest-params\n const args = arguments;\n let record: NetworkRecord | null = null;\n try {\n record = capture.onXhrSend(this, args[0]);\n } catch (e) {\n record = null;\n }\n try {\n return original(this, 'send').apply(this, args as unknown as unknown[]);\n } catch (error) {\n if (record) {\n capture.fail(record, error);\n const state = capture.xhrStates.get(this);\n if (state && state.record === record) {\n state.record = null;\n }\n }\n throw error;\n }\n };\n }\n\n private onXhrOpen(xhr: object, method: unknown, url: unknown): void {\n this.xhrStates.set(xhr, {\n method: String(method || 'GET').toUpperCase(),\n url: this.resolveUrl(isUrl(url) ? url.href : url),\n headers: {},\n record: null,\n headersAt: null,\n failure: null,\n loaded: false,\n });\n }\n\n private onXhrHeader(xhr: object, name: unknown, value: unknown): void {\n const state = this.xhrStates.get(xhr);\n if (state && typeof name === 'string') {\n addHeader(state.headers, name, String(value));\n }\n }\n\n private onXhrSend(xhr: object, body: unknown): NetworkRecord | null {\n if (!this.active) {\n return null;\n }\n const state = this.xhrStates.get(xhr);\n if (!state || !this.shouldCapture(state.url)) {\n return null;\n }\n this.listenToXhr(xhr as XMLHttpRequest);\n state.failure = null;\n state.loaded = false;\n state.headersAt = null;\n const headers: HeaderMap = { ...state.headers };\n const payload = state.method === 'GET' || state.method === 'HEAD' ? '' : this.requestPayload(body, headers);\n state.record = this.createRecord(state.method, state.url, headers, payload);\n return state.record;\n }\n\n private listenToXhr(xhr: XMLHttpRequest): void {\n if (this.xhrsWithListeners.has(xhr)) {\n return;\n }\n this.xhrsWithListeners.add(xhr);\n const state = () => this.xhrStates.get(xhr);\n const guard = (fn: (current: XhrState) => void) => () => {\n try {\n const current = state();\n if (current?.record) {\n fn(current);\n }\n } catch (e) {\n // Ignore.\n }\n };\n xhr.addEventListener(\n 'readystatechange',\n guard((current) => {\n if (current.headersAt === null && xhr.readyState >= 2) {\n current.headersAt = now();\n }\n }),\n );\n xhr.addEventListener(\n 'load',\n guard((current) => (current.loaded = true)),\n );\n xhr.addEventListener(\n 'abort',\n guard((current) => (current.failure = 'abort')),\n );\n xhr.addEventListener(\n 'timeout',\n guard((current) => (current.failure = 'timeout')),\n );\n xhr.addEventListener(\n 'error',\n guard((current) => (current.failure = 'error')),\n );\n xhr.addEventListener(\n 'loadend',\n guard((current) => this.onXhrLoadEnd(xhr, current)),\n );\n }\n\n private onXhrLoadEnd(xhr: XMLHttpRequest, state: XhrState): void {\n const record = state.record;\n if (!record) {\n return;\n }\n state.record = null;\n const finishedAt = now();\n\n if (state.failure || !state.loaded) {\n let errorText = 'Network request failed';\n if (state.failure === 'abort') {\n errorText = 'Request aborted';\n } else if (state.failure === 'timeout') {\n errorText = xhr.timeout > 0 ? `Request timed out after ${xhr.timeout} ms` : 'Request timed out';\n }\n this.update(record, (entry) => {\n entry.duration = Math.round(finishedAt - record.startedAt);\n entry.success = false;\n entry.response = { errorText };\n });\n return;\n }\n\n let rawHeaders = '';\n try {\n rawHeaders = xhr.getAllResponseHeaders();\n } catch (e) {\n rawHeaders = '';\n }\n const headers = parseRawHeaders(rawHeaders);\n this.update(record, (entry) => {\n entry.duration = Math.round((state.headersAt !== null ? state.headersAt : finishedAt) - record.startedAt);\n entry.success = true;\n entry.response = {\n status: xhr.status,\n statusText: xhr.statusText || '',\n headers,\n responseText: BODY_PENDING,\n };\n });\n let body: string | Promise<string>;\n try {\n body = this.xhrResponseBody(xhr, headers);\n } catch (e) {\n body = BODY_NOT_CAPTURED;\n }\n this.setResponseText(record, body);\n }\n\n /** The response is already in memory; only a bounded part of it is turned into text. */\n private xhrResponseBody(xhr: XMLHttpRequest, headers: HeaderMap): string | Promise<string> {\n const kind = classifyContentType(headers['content-type']);\n if (kind === 'streaming') {\n return STREAMING_BODY_OMITTED;\n }\n const responseType = xhr.responseType || '';\n if (kind === 'binary') {\n return BINARY_BODY_OMITTED;\n }\n if (responseType === '' || responseType === 'text') {\n const text: unknown = xhr.responseText;\n if (typeof text !== 'string') {\n return text === null || text === undefined ? '' : stringifyJsonHead(text);\n }\n if (kind === 'unknown' && text.indexOf('�') > -1) {\n // The browser had to replace invalid UTF-8: not a text body.\n return BINARY_BODY_OMITTED;\n }\n return capBodyText(text);\n }\n if (responseType === 'json') {\n const value: unknown = xhr.response;\n if (value === null || value === undefined) {\n return BODY_NOT_CAPTURED;\n }\n return typeof value === 'string' ? capBodyText(value) : stringifyJsonHead(value);\n }\n if (responseType === 'arraybuffer') {\n const bytes = toBytes(xhr.response);\n if (!bytes) {\n return BODY_NOT_CAPTURED;\n }\n return bytesToBodyText(bytes, kind, bytes.byteLength <= MAX_BODY_SIZE, bytes.byteLength);\n }\n if (responseType === 'blob') {\n const blob: unknown = xhr.response;\n if (!isBlob(blob)) {\n return BODY_NOT_CAPTURED;\n }\n return runOutsideZone(() => readBlobHead(blob, kind).catch(() => BODY_NOT_CAPTURED));\n }\n return BODY_NOT_CAPTURED;\n }\n\n // --------------------------------------------------------------- shared\n\n private requestPayload(body: unknown, headers: HeaderMap): string | Promise<string> {\n if (isUrlSearchParams(body) && !hasOwn(headers, 'content-type')) {\n // Sent with this content type by the browser; recorded so form fields can be redacted.\n headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';\n }\n const kind = classifyContentType(headers['content-type']);\n return runOutsideZone(() => captureRequestBody(body, kind));\n }\n\n private createRecord(\n method: string,\n url: string,\n headers: HeaderMap,\n payload: string | Promise<string>,\n ): NetworkRecord {\n const record: NetworkRecord = {\n id: this.nextId++,\n version: 0,\n startedAt: now(),\n entry: {\n date: new Date().toISOString(),\n type: method,\n url,\n request: {\n headers,\n payload: typeof payload === 'string' ? payload : BODY_PENDING,\n },\n },\n };\n if (typeof payload !== 'string') {\n const setPayload = (text: string) =>\n this.update(record, (entry) => {\n if (entry.request) {\n entry.request.payload = text;\n }\n });\n runOutsideZone(() => payload.then(setPayload, () => setPayload(BODY_NOT_CAPTURED)));\n }\n this.records.push(record);\n if (this.records.length > MAX_NETWORK_ENTRIES) {\n this.records.splice(0, this.records.length - MAX_NETWORK_ENTRIES);\n }\n this.onChange();\n return record;\n }\n\n private setResponseText(record: NetworkRecord, body: string | Promise<string>): void {\n const apply = (text: string) =>\n this.update(record, (entry) => {\n if (entry.response && entry.response.errorText === undefined) {\n entry.response.responseText = text;\n }\n });\n if (typeof body === 'string') {\n apply(body);\n return;\n }\n runOutsideZone(() => body.then(apply, () => apply(BODY_NOT_CAPTURED)));\n }\n\n private fail(record: NetworkRecord, error: unknown): void {\n try {\n this.update(record, (entry) => {\n entry.duration = Math.round(now() - record.startedAt);\n entry.success = false;\n entry.response = { errorText: describeError(error) };\n });\n } catch (e) {\n // Ignore.\n }\n }\n\n private update(record: NetworkRecord, mutate: (entry: GleapNetworkLogEntry) => void): void {\n try {\n mutate(record.entry);\n } catch (e) {\n // Ignore.\n }\n record.version++;\n if (this.active && this.records.indexOf(record) > -1) {\n this.onChange();\n }\n }\n\n private resolveUrl(url: unknown): string {\n const raw = typeof url === 'string' ? url : String(url);\n try {\n const doc = this.win.document;\n const base = doc?.baseURI || this.win.location.href;\n return new URL(raw, base).href;\n } catch (e) {\n return raw;\n }\n }\n\n /**\n * Only real network traffic: http(s) URLs that are not Gleap's own and not the app's bundled files\n * served by Capacitor's local server (http(s)://localhost on Android; capacitor:// on iOS).\n */\n private shouldCapture(url: string): boolean {\n const lower = url.toLowerCase();\n if (lower.indexOf('http://') !== 0 && lower.indexOf('https://') !== 0) {\n return false;\n }\n for (const host of DEFAULT_NETWORK_LOG_BLACKLIST) {\n if (lower.indexOf(host) > -1) {\n return false;\n }\n }\n try {\n const location = this.win.location;\n if (location.hostname === 'localhost' && !location.port) {\n return new URL(url).origin !== location.origin;\n }\n } catch (e) {\n // Ignore.\n }\n return true;\n }\n}\n\nfunction isRequest(value: unknown): value is Request {\n return typeof Request !== 'undefined' && value instanceof Request;\n}\n\nfunction isUrl(value: unknown): value is URL {\n return typeof URL !== 'undefined' && value instanceof URL;\n}\n\nfunction hasOwn(object: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(object, key);\n}\n\nfunction addHeader(headers: HeaderMap, name: string, value: string): void {\n const key = name.trim().toLowerCase();\n if (!key || key === '__proto__') {\n return;\n }\n headers[key] = hasOwn(headers, key) ? `${headers[key]}, ${value}` : value;\n}\n\n/** Headers | [name, value][] | record -> { lowercased name: value }, repeated names joined with \", \". */\nexport function normalizeHeaders(headers: unknown): HeaderMap {\n const result: HeaderMap = {};\n if (!headers) {\n return result;\n }\n try {\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n headers.forEach((value, name) => addHeader(result, name, value));\n return result;\n }\n if (Array.isArray(headers)) {\n for (const pair of headers) {\n if (pair && pair.length >= 2) {\n addHeader(result, String(pair[0]), String(pair[1]));\n }\n }\n return result;\n }\n if (typeof headers === 'object') {\n const record = headers as { [name: string]: unknown };\n for (const name of Object.keys(record)) {\n const value = record[name];\n if (value !== undefined && value !== null) {\n addHeader(result, name, String(value));\n }\n }\n }\n } catch (e) {\n // Ignore.\n }\n return result;\n}\n\nfunction parseRawHeaders(raw: string): HeaderMap {\n const result: HeaderMap = {};\n if (typeof raw !== 'string') {\n return result;\n }\n for (const line of raw.split(/\\r?\\n/)) {\n const index = line.indexOf(':');\n if (index > 0) {\n addHeader(result, line.slice(0, index), line.slice(index + 1).trim());\n }\n }\n return result;\n}\n\n/** content-length when it describes the decoded body (no content-encoding), else null. */\nfunction identityContentLength(headers: HeaderMap): number | null {\n const encoding = (headers['content-encoding'] || '').trim().toLowerCase();\n if (encoding && encoding !== 'identity') {\n return null;\n }\n const length = parseInt(headers['content-length'] || '', 10);\n return isFinite(length) && length >= 0 ? length : null;\n}\n\nfunction describeError(error: unknown): string {\n try {\n if (error && typeof error === 'object') {\n const { name, message } = error as { name?: unknown; message?: unknown };\n const text = typeof message === 'string' ? message : '';\n if (name === 'AbortError') {\n return text ? `Request aborted (${text})` : 'Request aborted';\n }\n if (name === 'TimeoutError') {\n return text ? `Request timed out (${text})` : 'Request timed out';\n }\n if (text) {\n return typeof name === 'string' && name ? `${name}: ${text}` : text;\n }\n }\n const text = String(error);\n return text && text !== 'undefined' ? text : 'Request failed';\n } catch (e) {\n return 'Request failed';\n }\n}\n"]}
@@ -0,0 +1,54 @@
1
+ import type { GleapNetworkLogEntry } from '../definitions';
2
+ /** URLs containing one of these are never logged, in addition to the configured blacklist. */
3
+ export declare const DEFAULT_NETWORK_LOG_BLACKLIST: readonly string[];
4
+ export declare const REDACTED_VALUE = "[REDACTED]";
5
+ export declare const BODY_NOT_CAPTURED = "[body not captured]";
6
+ export interface RedactionRules {
7
+ /** Lowercased props, matched as whole header names, JSON keys, form fields and query params. */
8
+ props: Set<string>;
9
+ /** Lowercased props containing a dot, split into a path that is applied from the JSON root. */
10
+ paths: string[][];
11
+ /** Lowercased blacklist entries, including the default Gleap hosts. */
12
+ blacklist: string[];
13
+ }
14
+ /**
15
+ * Builds the redaction rules from the props to ignore and the blacklist (remote config and local
16
+ * setter calls combined by the caller). Entries are trimmed, lowercased and deduplicated.
17
+ */
18
+ export declare function createRedactionRules(propsToIgnore?: readonly unknown[] | null, blacklist?: readonly unknown[] | null): RedactionRules;
19
+ /** Substring match (case-insensitive) against the blacklist, incl. the default Gleap hosts. */
20
+ export declare function isBlacklistedUrl(url: unknown, rules: RedactionRules): boolean;
21
+ /**
22
+ * Removes headers named like a prop (case-insensitive) and masks the credential headers.
23
+ * Returns a new object; the input is not modified.
24
+ */
25
+ export declare function redactHeaders(headers: {
26
+ [name: string]: string;
27
+ } | undefined, rules: RedactionRules): {
28
+ [name: string]: string;
29
+ } | undefined;
30
+ /**
31
+ * Removes matching keys from a JSON body: every key equal to a prop at any depth (objects inside
32
+ * arrays too), and dotted props additionally as a path from the root, then re-serialises compactly.
33
+ * A body that looks like JSON but does not parse (e.g. cut at the size limit) gets the values of
34
+ * matching keys masked in the text instead. Returns the body untouched when nothing matched.
35
+ */
36
+ export declare function redactJsonBody(body: string, rules: RedactionRules): string;
37
+ /**
38
+ * Removes form fields (application/x-www-form-urlencoded) named like a prop. Kept fields keep their
39
+ * original encoding; the body is returned untouched when nothing matched.
40
+ */
41
+ export declare function redactFormBody(body: string, rules: RedactionRules): string;
42
+ /** Removes query parameters named like a prop. The URL is returned untouched when nothing matched. */
43
+ export declare function redactUrl(url: string, rules: RedactionRules): string;
44
+ /** Redacts one entry. Returns a new entry; the input is not modified. */
45
+ export declare function redactNetworkLogEntry(entry: GleapNetworkLogEntry, rules: RedactionRules): GleapNetworkLogEntry;
46
+ /**
47
+ * Drops blacklisted entries and redacts the rest. An entry that cannot be redacted (e.g. JSON nested
48
+ * too deeply) is sent without bodies, headers and query instead of unredacted.
49
+ */
50
+ export declare function redactNetworkLogs(entries: readonly GleapNetworkLogEntry[], rules: RedactionRules): GleapNetworkLogEntry[];
51
+ /** Like redactNetworkLogEntry, but never throws: falls back to an entry without any content. */
52
+ export declare function redactNetworkLogEntryOrStrip(entry: GleapNetworkLogEntry, rules: RedactionRules): GleapNetworkLogEntry;
53
+ /** Keeps method, URL (without query), timing and status; drops headers and bodies. */
54
+ export declare function stripNetworkLogEntry(entry: GleapNetworkLogEntry): GleapNetworkLogEntry;
@@ -0,0 +1,388 @@
1
+ /** URLs containing one of these are never logged, in addition to the configured blacklist. */
2
+ export const DEFAULT_NETWORK_LOG_BLACKLIST = ['gleap.io', 'gleap.ai'];
3
+ export const REDACTED_VALUE = '[REDACTED]';
4
+ export const BODY_NOT_CAPTURED = '[body not captured]';
5
+ /** Credential headers whose value is always masked (the header itself is kept). */
6
+ const ALWAYS_MASKED_HEADERS = ['authorization', 'proxy-authorization', 'cookie', 'set-cookie'];
7
+ /**
8
+ * Builds the redaction rules from the props to ignore and the blacklist (remote config and local
9
+ * setter calls combined by the caller). Entries are trimmed, lowercased and deduplicated.
10
+ */
11
+ export function createRedactionRules(propsToIgnore, blacklist) {
12
+ const props = new Set();
13
+ const paths = [];
14
+ for (const raw of propsToIgnore || []) {
15
+ if (typeof raw !== 'string') {
16
+ continue;
17
+ }
18
+ const prop = raw.trim().toLowerCase();
19
+ if (!prop || props.has(prop)) {
20
+ continue;
21
+ }
22
+ props.add(prop);
23
+ if (prop.indexOf('.') > -1) {
24
+ const segments = prop.split('.').filter((segment) => segment.length > 0);
25
+ if (segments.length > 1) {
26
+ paths.push(segments);
27
+ }
28
+ }
29
+ }
30
+ const blacklistEntries = [];
31
+ for (const raw of [...DEFAULT_NETWORK_LOG_BLACKLIST, ...(blacklist || [])]) {
32
+ if (typeof raw !== 'string') {
33
+ continue;
34
+ }
35
+ const entry = raw.trim().toLowerCase();
36
+ if (entry && blacklistEntries.indexOf(entry) < 0) {
37
+ blacklistEntries.push(entry);
38
+ }
39
+ }
40
+ return { props, paths, blacklist: blacklistEntries };
41
+ }
42
+ /** Substring match (case-insensitive) against the blacklist, incl. the default Gleap hosts. */
43
+ export function isBlacklistedUrl(url, rules) {
44
+ if (typeof url !== 'string') {
45
+ return false;
46
+ }
47
+ const lowerUrl = url.toLowerCase();
48
+ for (const entry of rules.blacklist) {
49
+ if (lowerUrl.indexOf(entry) > -1) {
50
+ return true;
51
+ }
52
+ }
53
+ return false;
54
+ }
55
+ /**
56
+ * Removes headers named like a prop (case-insensitive) and masks the credential headers.
57
+ * Returns a new object; the input is not modified.
58
+ */
59
+ export function redactHeaders(headers, rules) {
60
+ if (!headers || typeof headers !== 'object') {
61
+ return headers;
62
+ }
63
+ const result = {};
64
+ for (const name of Object.keys(headers)) {
65
+ const lowerName = name.toLowerCase();
66
+ if (rules.props.has(lowerName)) {
67
+ continue;
68
+ }
69
+ result[name] = ALWAYS_MASKED_HEADERS.indexOf(lowerName) > -1 ? REDACTED_VALUE : headers[name];
70
+ }
71
+ return result;
72
+ }
73
+ /**
74
+ * Removes matching keys from a JSON body: every key equal to a prop at any depth (objects inside
75
+ * arrays too), and dotted props additionally as a path from the root, then re-serialises compactly.
76
+ * A body that looks like JSON but does not parse (e.g. cut at the size limit) gets the values of
77
+ * matching keys masked in the text instead. Returns the body untouched when nothing matched.
78
+ */
79
+ export function redactJsonBody(body, rules) {
80
+ if (!body || rules.props.size === 0) {
81
+ return body;
82
+ }
83
+ const firstChar = firstNonWhitespaceChar(body);
84
+ if (firstChar !== '{' && firstChar !== '[') {
85
+ return body;
86
+ }
87
+ let parsed;
88
+ try {
89
+ parsed = JSON.parse(body);
90
+ }
91
+ catch (e) {
92
+ return maskJsonKeysInText(body, rules);
93
+ }
94
+ let changed = removeKeysAtAnyDepth(parsed, rules.props);
95
+ for (const path of rules.paths) {
96
+ if (removePath(parsed, path, 0)) {
97
+ changed = true;
98
+ }
99
+ }
100
+ return changed ? JSON.stringify(parsed) : body;
101
+ }
102
+ /**
103
+ * Removes form fields (application/x-www-form-urlencoded) named like a prop. Kept fields keep their
104
+ * original encoding; the body is returned untouched when nothing matched.
105
+ */
106
+ export function redactFormBody(body, rules) {
107
+ if (!body || rules.props.size === 0) {
108
+ return body;
109
+ }
110
+ const filtered = filterParams(body, rules);
111
+ return filtered === null ? body : filtered;
112
+ }
113
+ /** Removes query parameters named like a prop. The URL is returned untouched when nothing matched. */
114
+ export function redactUrl(url, rules) {
115
+ if (typeof url !== 'string' || rules.props.size === 0) {
116
+ return url;
117
+ }
118
+ const hashIndex = url.indexOf('#');
119
+ const main = hashIndex > -1 ? url.slice(0, hashIndex) : url;
120
+ const hash = hashIndex > -1 ? url.slice(hashIndex) : '';
121
+ const queryIndex = main.indexOf('?');
122
+ if (queryIndex < 0) {
123
+ return url;
124
+ }
125
+ const filtered = filterParams(main.slice(queryIndex + 1), rules);
126
+ if (filtered === null) {
127
+ return url;
128
+ }
129
+ return main.slice(0, queryIndex) + (filtered ? `?${filtered}` : '') + hash;
130
+ }
131
+ /** Redacts one entry. Returns a new entry; the input is not modified. */
132
+ export function redactNetworkLogEntry(entry, rules) {
133
+ const result = Object.assign({}, entry);
134
+ result.url = redactUrl(entry.url, rules);
135
+ if (entry.request) {
136
+ const request = Object.assign({}, entry.request);
137
+ const contentType = getHeader(entry.request.headers, 'content-type');
138
+ request.headers = redactHeaders(entry.request.headers, rules);
139
+ if (typeof request.payload === 'string') {
140
+ request.payload = redactBody(request.payload, contentType, rules);
141
+ }
142
+ result.request = request;
143
+ }
144
+ if (entry.response) {
145
+ const response = Object.assign({}, entry.response);
146
+ const contentType = getHeader(entry.response.headers, 'content-type');
147
+ if (response.headers) {
148
+ response.headers = redactHeaders(response.headers, rules);
149
+ }
150
+ if (typeof response.responseText === 'string') {
151
+ response.responseText = redactBody(response.responseText, contentType, rules);
152
+ }
153
+ result.response = response;
154
+ }
155
+ return result;
156
+ }
157
+ /**
158
+ * Drops blacklisted entries and redacts the rest. An entry that cannot be redacted (e.g. JSON nested
159
+ * too deeply) is sent without bodies, headers and query instead of unredacted.
160
+ */
161
+ export function redactNetworkLogs(entries, rules) {
162
+ const result = [];
163
+ for (const entry of entries) {
164
+ if (!entry || isBlacklistedUrl(entry.url, rules)) {
165
+ continue;
166
+ }
167
+ result.push(redactNetworkLogEntryOrStrip(entry, rules));
168
+ }
169
+ return result;
170
+ }
171
+ /** Like redactNetworkLogEntry, but never throws: falls back to an entry without any content. */
172
+ export function redactNetworkLogEntryOrStrip(entry, rules) {
173
+ try {
174
+ return redactNetworkLogEntry(entry, rules);
175
+ }
176
+ catch (e) {
177
+ return stripNetworkLogEntry(entry);
178
+ }
179
+ }
180
+ /** Keeps method, URL (without query), timing and status; drops headers and bodies. */
181
+ export function stripNetworkLogEntry(entry) {
182
+ const url = typeof entry.url === 'string' ? entry.url.split(/[?#]/)[0] : '';
183
+ const stripped = {
184
+ date: entry.date,
185
+ type: entry.type,
186
+ url,
187
+ duration: entry.duration,
188
+ success: entry.success,
189
+ request: { headers: {}, payload: BODY_NOT_CAPTURED },
190
+ };
191
+ if (entry.response) {
192
+ stripped.response =
193
+ typeof entry.response.errorText === 'string'
194
+ ? { errorText: entry.response.errorText }
195
+ : {
196
+ status: entry.response.status,
197
+ statusText: entry.response.statusText,
198
+ headers: {},
199
+ responseText: BODY_NOT_CAPTURED,
200
+ };
201
+ }
202
+ return stripped;
203
+ }
204
+ function redactBody(body, contentType, rules) {
205
+ if (!body || rules.props.size === 0) {
206
+ return body;
207
+ }
208
+ const json = redactJsonBody(body, rules);
209
+ if (json !== body) {
210
+ return json;
211
+ }
212
+ const lowerContentType = (contentType || '').toLowerCase();
213
+ if (lowerContentType.indexOf('x-www-form-urlencoded') > -1 || (!lowerContentType && looksLikeFormBody(body))) {
214
+ return redactFormBody(body, rules);
215
+ }
216
+ return body;
217
+ }
218
+ function looksLikeFormBody(body) {
219
+ return /^[^\s=&]+=[^\s&]*(?:&[^\s=&]*(?:=[^\s&]*)?)*$/.test(body);
220
+ }
221
+ function getHeader(headers, name) {
222
+ if (!headers || typeof headers !== 'object') {
223
+ return undefined;
224
+ }
225
+ for (const key of Object.keys(headers)) {
226
+ if (key.toLowerCase() === name) {
227
+ return headers[key];
228
+ }
229
+ }
230
+ return undefined;
231
+ }
232
+ function firstNonWhitespaceChar(text) {
233
+ const match = /\S/.exec(text);
234
+ return match ? match[0] : '';
235
+ }
236
+ /**
237
+ * Masks the values of matching keys in JSON text that does not parse: every prop as a whole plus the
238
+ * last segment of each dotted prop, case-insensitive. A string cut off at the end is masked too;
239
+ * object and array values are left alone (their inner keys are matched on their own).
240
+ */
241
+ function maskJsonKeysInText(body, rules) {
242
+ const keys = new Set(rules.props);
243
+ for (const path of rules.paths) {
244
+ keys.add(path[path.length - 1]);
245
+ }
246
+ let result = body;
247
+ keys.forEach((key) => {
248
+ // A JSON string never contains a raw line break, so a string cut at the end stops before the
249
+ // "\n… [truncated" marker instead of swallowing it.
250
+ const pattern = new RegExp(`"(${escapeRegExp(key)})"(\\s*:\\s*)("(?:[^"\\\\\\r\\n]|\\\\.)*"?|-?\\d[0-9.eE+-]*|true|false|null)`, 'gi');
251
+ result = result.replace(pattern, `"$1"$2"${REDACTED_VALUE}"`);
252
+ });
253
+ return result === body ? body : result;
254
+ }
255
+ function escapeRegExp(text) {
256
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
257
+ }
258
+ /** Removes every key equal to a prop at any depth. Iterative, so deep JSON cannot overflow the stack. */
259
+ function removeKeysAtAnyDepth(root, props) {
260
+ let changed = false;
261
+ const stack = [root];
262
+ while (stack.length > 0) {
263
+ const node = stack.pop();
264
+ if (Array.isArray(node)) {
265
+ for (const item of node) {
266
+ if (item && typeof item === 'object') {
267
+ stack.push(item);
268
+ }
269
+ }
270
+ }
271
+ else if (node && typeof node === 'object') {
272
+ const record = node;
273
+ for (const key of Object.keys(record)) {
274
+ if (props.has(key.toLowerCase())) {
275
+ delete record[key];
276
+ changed = true;
277
+ }
278
+ else {
279
+ const child = record[key];
280
+ if (child && typeof child === 'object') {
281
+ stack.push(child);
282
+ }
283
+ }
284
+ }
285
+ }
286
+ }
287
+ return changed;
288
+ }
289
+ /** Removes a dotted path from the root; arrays on the way are applied to each element. */
290
+ function removePath(node, segments, index) {
291
+ if (Array.isArray(node)) {
292
+ let changed = false;
293
+ for (const item of node) {
294
+ if (removePath(item, segments, index)) {
295
+ changed = true;
296
+ }
297
+ }
298
+ return changed;
299
+ }
300
+ if (!node || typeof node !== 'object') {
301
+ return false;
302
+ }
303
+ const record = node;
304
+ const segment = segments[index];
305
+ const isLast = index === segments.length - 1;
306
+ let changed = false;
307
+ for (const key of Object.keys(record)) {
308
+ if (key.toLowerCase() !== segment) {
309
+ continue;
310
+ }
311
+ if (isLast) {
312
+ delete record[key];
313
+ changed = true;
314
+ }
315
+ else if (removePath(record[key], segments, index + 1)) {
316
+ changed = true;
317
+ }
318
+ }
319
+ return changed;
320
+ }
321
+ /**
322
+ * Filters an urlencoded parameter list (query string or form body). Returns null when nothing was
323
+ * removed, so callers can keep the original string.
324
+ */
325
+ function filterParams(params, rules) {
326
+ const parts = params.split('&');
327
+ const kept = [];
328
+ let changed = false;
329
+ for (const part of parts) {
330
+ const equalsIndex = part.indexOf('=');
331
+ const rawName = equalsIndex > -1 ? part.slice(0, equalsIndex) : part;
332
+ if (rawName && paramNameMatches(decodeParamName(rawName), rules)) {
333
+ changed = true;
334
+ continue;
335
+ }
336
+ kept.push(part);
337
+ }
338
+ return changed ? kept.join('&') : null;
339
+ }
340
+ function decodeParamName(rawName) {
341
+ try {
342
+ return decodeURIComponent(rawName.replace(/\+/g, ' '));
343
+ }
344
+ catch (e) {
345
+ return rawName;
346
+ }
347
+ }
348
+ /**
349
+ * A param matches when its whole name equals a prop. Bracket names (user[password]) are treated like
350
+ * nested JSON keys: any segment equal to a prop, or a dotted prop matching the leading segments.
351
+ */
352
+ function paramNameMatches(name, rules) {
353
+ const lowerName = name.toLowerCase();
354
+ if (rules.props.has(lowerName)) {
355
+ return true;
356
+ }
357
+ if (lowerName.indexOf('[') < 0) {
358
+ return false;
359
+ }
360
+ const segments = lowerName
361
+ .replace(/\]/g, '')
362
+ .split('[')
363
+ .filter((segment) => segment.length > 0);
364
+ if (segments.length < 2) {
365
+ return false;
366
+ }
367
+ for (const segment of segments) {
368
+ if (rules.props.has(segment)) {
369
+ return true;
370
+ }
371
+ }
372
+ for (const path of rules.paths) {
373
+ if (path.length <= segments.length) {
374
+ let matches = true;
375
+ for (let i = 0; i < path.length; i++) {
376
+ if (path[i] !== segments[i]) {
377
+ matches = false;
378
+ break;
379
+ }
380
+ }
381
+ if (matches) {
382
+ return true;
383
+ }
384
+ }
385
+ }
386
+ return false;
387
+ }
388
+ //# sourceMappingURL=redaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redaction.js","sourceRoot":"","sources":["../../../src/logs/redaction.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GleapNetworkLogEntry } from '../definitions';\n\n/** URLs containing one of these are never logged, in addition to the configured blacklist. */\nexport const DEFAULT_NETWORK_LOG_BLACKLIST: readonly string[] = ['gleap.io', 'gleap.ai'];\n\nexport const REDACTED_VALUE = '[REDACTED]';\nexport const BODY_NOT_CAPTURED = '[body not captured]';\n\n/** Credential headers whose value is always masked (the header itself is kept). */\nconst ALWAYS_MASKED_HEADERS = ['authorization', 'proxy-authorization', 'cookie', 'set-cookie'];\n\nexport interface RedactionRules {\n /** Lowercased props, matched as whole header names, JSON keys, form fields and query params. */\n props: Set<string>;\n /** Lowercased props containing a dot, split into a path that is applied from the JSON root. */\n paths: string[][];\n /** Lowercased blacklist entries, including the default Gleap hosts. */\n blacklist: string[];\n}\n\n/**\n * Builds the redaction rules from the props to ignore and the blacklist (remote config and local\n * setter calls combined by the caller). Entries are trimmed, lowercased and deduplicated.\n */\nexport function createRedactionRules(\n propsToIgnore?: readonly unknown[] | null,\n blacklist?: readonly unknown[] | null,\n): RedactionRules {\n const props = new Set<string>();\n const paths: string[][] = [];\n for (const raw of propsToIgnore || []) {\n if (typeof raw !== 'string') {\n continue;\n }\n const prop = raw.trim().toLowerCase();\n if (!prop || props.has(prop)) {\n continue;\n }\n props.add(prop);\n if (prop.indexOf('.') > -1) {\n const segments = prop.split('.').filter((segment) => segment.length > 0);\n if (segments.length > 1) {\n paths.push(segments);\n }\n }\n }\n\n const blacklistEntries: string[] = [];\n for (const raw of [...DEFAULT_NETWORK_LOG_BLACKLIST, ...(blacklist || [])]) {\n if (typeof raw !== 'string') {\n continue;\n }\n const entry = raw.trim().toLowerCase();\n if (entry && blacklistEntries.indexOf(entry) < 0) {\n blacklistEntries.push(entry);\n }\n }\n\n return { props, paths, blacklist: blacklistEntries };\n}\n\n/** Substring match (case-insensitive) against the blacklist, incl. the default Gleap hosts. */\nexport function isBlacklistedUrl(url: unknown, rules: RedactionRules): boolean {\n if (typeof url !== 'string') {\n return false;\n }\n const lowerUrl = url.toLowerCase();\n for (const entry of rules.blacklist) {\n if (lowerUrl.indexOf(entry) > -1) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Removes headers named like a prop (case-insensitive) and masks the credential headers.\n * Returns a new object; the input is not modified.\n */\nexport function redactHeaders(\n headers: { [name: string]: string } | undefined,\n rules: RedactionRules,\n): { [name: string]: string } | undefined {\n if (!headers || typeof headers !== 'object') {\n return headers;\n }\n const result: { [name: string]: string } = {};\n for (const name of Object.keys(headers)) {\n const lowerName = name.toLowerCase();\n if (rules.props.has(lowerName)) {\n continue;\n }\n result[name] = ALWAYS_MASKED_HEADERS.indexOf(lowerName) > -1 ? REDACTED_VALUE : headers[name];\n }\n return result;\n}\n\n/**\n * Removes matching keys from a JSON body: every key equal to a prop at any depth (objects inside\n * arrays too), and dotted props additionally as a path from the root, then re-serialises compactly.\n * A body that looks like JSON but does not parse (e.g. cut at the size limit) gets the values of\n * matching keys masked in the text instead. Returns the body untouched when nothing matched.\n */\nexport function redactJsonBody(body: string, rules: RedactionRules): string {\n if (!body || rules.props.size === 0) {\n return body;\n }\n const firstChar = firstNonWhitespaceChar(body);\n if (firstChar !== '{' && firstChar !== '[') {\n return body;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch (e) {\n return maskJsonKeysInText(body, rules);\n }\n\n let changed = removeKeysAtAnyDepth(parsed, rules.props);\n for (const path of rules.paths) {\n if (removePath(parsed, path, 0)) {\n changed = true;\n }\n }\n return changed ? JSON.stringify(parsed) : body;\n}\n\n/**\n * Removes form fields (application/x-www-form-urlencoded) named like a prop. Kept fields keep their\n * original encoding; the body is returned untouched when nothing matched.\n */\nexport function redactFormBody(body: string, rules: RedactionRules): string {\n if (!body || rules.props.size === 0) {\n return body;\n }\n const filtered = filterParams(body, rules);\n return filtered === null ? body : filtered;\n}\n\n/** Removes query parameters named like a prop. The URL is returned untouched when nothing matched. */\nexport function redactUrl(url: string, rules: RedactionRules): string {\n if (typeof url !== 'string' || rules.props.size === 0) {\n return url;\n }\n const hashIndex = url.indexOf('#');\n const main = hashIndex > -1 ? url.slice(0, hashIndex) : url;\n const hash = hashIndex > -1 ? url.slice(hashIndex) : '';\n const queryIndex = main.indexOf('?');\n if (queryIndex < 0) {\n return url;\n }\n const filtered = filterParams(main.slice(queryIndex + 1), rules);\n if (filtered === null) {\n return url;\n }\n return main.slice(0, queryIndex) + (filtered ? `?${filtered}` : '') + hash;\n}\n\n/** Redacts one entry. Returns a new entry; the input is not modified. */\nexport function redactNetworkLogEntry(entry: GleapNetworkLogEntry, rules: RedactionRules): GleapNetworkLogEntry {\n const result: GleapNetworkLogEntry = { ...entry };\n result.url = redactUrl(entry.url, rules);\n\n if (entry.request) {\n const request = { ...entry.request };\n const contentType = getHeader(entry.request.headers, 'content-type');\n request.headers = redactHeaders(entry.request.headers, rules);\n if (typeof request.payload === 'string') {\n request.payload = redactBody(request.payload, contentType, rules);\n }\n result.request = request;\n }\n\n if (entry.response) {\n const response = { ...entry.response };\n const contentType = getHeader(entry.response.headers, 'content-type');\n if (response.headers) {\n response.headers = redactHeaders(response.headers, rules);\n }\n if (typeof response.responseText === 'string') {\n response.responseText = redactBody(response.responseText, contentType, rules);\n }\n result.response = response;\n }\n\n return result;\n}\n\n/**\n * Drops blacklisted entries and redacts the rest. An entry that cannot be redacted (e.g. JSON nested\n * too deeply) is sent without bodies, headers and query instead of unredacted.\n */\nexport function redactNetworkLogs(\n entries: readonly GleapNetworkLogEntry[],\n rules: RedactionRules,\n): GleapNetworkLogEntry[] {\n const result: GleapNetworkLogEntry[] = [];\n for (const entry of entries) {\n if (!entry || isBlacklistedUrl(entry.url, rules)) {\n continue;\n }\n result.push(redactNetworkLogEntryOrStrip(entry, rules));\n }\n return result;\n}\n\n/** Like redactNetworkLogEntry, but never throws: falls back to an entry without any content. */\nexport function redactNetworkLogEntryOrStrip(entry: GleapNetworkLogEntry, rules: RedactionRules): GleapNetworkLogEntry {\n try {\n return redactNetworkLogEntry(entry, rules);\n } catch (e) {\n return stripNetworkLogEntry(entry);\n }\n}\n\n/** Keeps method, URL (without query), timing and status; drops headers and bodies. */\nexport function stripNetworkLogEntry(entry: GleapNetworkLogEntry): GleapNetworkLogEntry {\n const url = typeof entry.url === 'string' ? entry.url.split(/[?#]/)[0] : '';\n const stripped: GleapNetworkLogEntry = {\n date: entry.date,\n type: entry.type,\n url,\n duration: entry.duration,\n success: entry.success,\n request: { headers: {}, payload: BODY_NOT_CAPTURED },\n };\n if (entry.response) {\n stripped.response =\n typeof entry.response.errorText === 'string'\n ? { errorText: entry.response.errorText }\n : {\n status: entry.response.status,\n statusText: entry.response.statusText,\n headers: {},\n responseText: BODY_NOT_CAPTURED,\n };\n }\n return stripped;\n}\n\nfunction redactBody(body: string, contentType: string | undefined, rules: RedactionRules): string {\n if (!body || rules.props.size === 0) {\n return body;\n }\n const json = redactJsonBody(body, rules);\n if (json !== body) {\n return json;\n }\n const lowerContentType = (contentType || '').toLowerCase();\n if (lowerContentType.indexOf('x-www-form-urlencoded') > -1 || (!lowerContentType && looksLikeFormBody(body))) {\n return redactFormBody(body, rules);\n }\n return body;\n}\n\nfunction looksLikeFormBody(body: string): boolean {\n return /^[^\\s=&]+=[^\\s&]*(?:&[^\\s=&]*(?:=[^\\s&]*)?)*$/.test(body);\n}\n\nfunction getHeader(headers: { [name: string]: string } | undefined, name: string): string | undefined {\n if (!headers || typeof headers !== 'object') {\n return undefined;\n }\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === name) {\n return headers[key];\n }\n }\n return undefined;\n}\n\nfunction firstNonWhitespaceChar(text: string): string {\n const match = /\\S/.exec(text);\n return match ? match[0] : '';\n}\n\n/**\n * Masks the values of matching keys in JSON text that does not parse: every prop as a whole plus the\n * last segment of each dotted prop, case-insensitive. A string cut off at the end is masked too;\n * object and array values are left alone (their inner keys are matched on their own).\n */\nfunction maskJsonKeysInText(body: string, rules: RedactionRules): string {\n const keys = new Set<string>(rules.props);\n for (const path of rules.paths) {\n keys.add(path[path.length - 1]);\n }\n let result = body;\n keys.forEach((key) => {\n // A JSON string never contains a raw line break, so a string cut at the end stops before the\n // \"\\n… [truncated\" marker instead of swallowing it.\n const pattern = new RegExp(\n `\"(${escapeRegExp(key)})\"(\\\\s*:\\\\s*)(\"(?:[^\"\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*\"?|-?\\\\d[0-9.eE+-]*|true|false|null)`,\n 'gi',\n );\n result = result.replace(pattern, `\"$1\"$2\"${REDACTED_VALUE}\"`);\n });\n return result === body ? body : result;\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Removes every key equal to a prop at any depth. Iterative, so deep JSON cannot overflow the stack. */\nfunction removeKeysAtAnyDepth(root: unknown, props: Set<string>): boolean {\n let changed = false;\n const stack: unknown[] = [root];\n while (stack.length > 0) {\n const node = stack.pop();\n if (Array.isArray(node)) {\n for (const item of node) {\n if (item && typeof item === 'object') {\n stack.push(item);\n }\n }\n } else if (node && typeof node === 'object') {\n const record = node as { [key: string]: unknown };\n for (const key of Object.keys(record)) {\n if (props.has(key.toLowerCase())) {\n delete record[key];\n changed = true;\n } else {\n const child = record[key];\n if (child && typeof child === 'object') {\n stack.push(child);\n }\n }\n }\n }\n }\n return changed;\n}\n\n/** Removes a dotted path from the root; arrays on the way are applied to each element. */\nfunction removePath(node: unknown, segments: string[], index: number): boolean {\n if (Array.isArray(node)) {\n let changed = false;\n for (const item of node) {\n if (removePath(item, segments, index)) {\n changed = true;\n }\n }\n return changed;\n }\n if (!node || typeof node !== 'object') {\n return false;\n }\n const record = node as { [key: string]: unknown };\n const segment = segments[index];\n const isLast = index === segments.length - 1;\n let changed = false;\n for (const key of Object.keys(record)) {\n if (key.toLowerCase() !== segment) {\n continue;\n }\n if (isLast) {\n delete record[key];\n changed = true;\n } else if (removePath(record[key], segments, index + 1)) {\n changed = true;\n }\n }\n return changed;\n}\n\n/**\n * Filters an urlencoded parameter list (query string or form body). Returns null when nothing was\n * removed, so callers can keep the original string.\n */\nfunction filterParams(params: string, rules: RedactionRules): string | null {\n const parts = params.split('&');\n const kept: string[] = [];\n let changed = false;\n for (const part of parts) {\n const equalsIndex = part.indexOf('=');\n const rawName = equalsIndex > -1 ? part.slice(0, equalsIndex) : part;\n if (rawName && paramNameMatches(decodeParamName(rawName), rules)) {\n changed = true;\n continue;\n }\n kept.push(part);\n }\n return changed ? kept.join('&') : null;\n}\n\nfunction decodeParamName(rawName: string): string {\n try {\n return decodeURIComponent(rawName.replace(/\\+/g, ' '));\n } catch (e) {\n return rawName;\n }\n}\n\n/**\n * A param matches when its whole name equals a prop. Bracket names (user[password]) are treated like\n * nested JSON keys: any segment equal to a prop, or a dotted prop matching the leading segments.\n */\nfunction paramNameMatches(name: string, rules: RedactionRules): boolean {\n const lowerName = name.toLowerCase();\n if (rules.props.has(lowerName)) {\n return true;\n }\n if (lowerName.indexOf('[') < 0) {\n return false;\n }\n const segments = lowerName\n .replace(/\\]/g, '')\n .split('[')\n .filter((segment) => segment.length > 0);\n if (segments.length < 2) {\n return false;\n }\n for (const segment of segments) {\n if (rules.props.has(segment)) {\n return true;\n }\n }\n for (const path of rules.paths) {\n if (path.length <= segments.length) {\n let matches = true;\n for (let i = 0; i < path.length; i++) {\n if (path[i] !== segments[i]) {\n matches = false;\n break;\n }\n }\n if (matches) {\n return true;\n }\n }\n }\n return false;\n}\n"]}