@amplitude/session-replay-browser 1.47.4 → 1.48.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 (38) hide show
  1. package/lib/cjs/config/types.d.ts +3 -2
  2. package/lib/cjs/config/types.d.ts.map +1 -1
  3. package/lib/cjs/config/types.js.map +1 -1
  4. package/lib/cjs/network-body-capture.d.ts +21 -0
  5. package/lib/cjs/network-body-capture.d.ts.map +1 -0
  6. package/lib/cjs/network-body-capture.js +47 -0
  7. package/lib/cjs/network-body-capture.js.map +1 -0
  8. package/lib/cjs/observers.d.ts +3 -2
  9. package/lib/cjs/observers.d.ts.map +1 -1
  10. package/lib/cjs/observers.js +5 -4
  11. package/lib/cjs/observers.js.map +1 -1
  12. package/lib/cjs/version.d.ts +1 -1
  13. package/lib/cjs/version.js +1 -1
  14. package/lib/cjs/version.js.map +1 -1
  15. package/lib/esm/config/types.d.ts +3 -2
  16. package/lib/esm/config/types.d.ts.map +1 -1
  17. package/lib/esm/config/types.js.map +1 -1
  18. package/lib/esm/network-body-capture.d.ts +21 -0
  19. package/lib/esm/network-body-capture.d.ts.map +1 -0
  20. package/lib/esm/network-body-capture.js +40 -0
  21. package/lib/esm/network-body-capture.js.map +1 -0
  22. package/lib/esm/observers.d.ts +3 -2
  23. package/lib/esm/observers.d.ts.map +1 -1
  24. package/lib/esm/observers.js +5 -4
  25. package/lib/esm/observers.js.map +1 -1
  26. package/lib/esm/version.d.ts +1 -1
  27. package/lib/esm/version.js +1 -1
  28. package/lib/esm/version.js.map +1 -1
  29. package/lib/scripts/index-min.js +1 -1
  30. package/lib/scripts/index-min.js.gz +0 -0
  31. package/lib/scripts/index-min.js.map +1 -1
  32. package/lib/scripts/observers-min.js +1 -1
  33. package/lib/scripts/observers-min.js.gz +0 -0
  34. package/lib/scripts/observers-min.js.map +1 -1
  35. package/lib/scripts/session-replay-browser-min.js +1 -1
  36. package/lib/scripts/session-replay-browser-min.js.gz +0 -0
  37. package/lib/scripts/session-replay-browser-min.js.map +1 -1
  38. package/package.json +4 -4
@@ -1,2 +1,2 @@
1
- import{c as t}from"./targeting-min.js";import{g as e}from"./index-min.js";const n=["image/","audio/","video/","application/octet-stream","font/"];function o(t,e){if(new Blob([t]).size<=e)return{value:t,truncated:!1};let n=0,o=Math.min(t.length,e);for(;n<o;){const s=Math.ceil((n+o)/2);new Blob([t.slice(0,s)]).size<=e?n=s:o=s-1}return n>0&&t.charCodeAt(n-1)>=55296&&t.charCodeAt(n-1)<=56319&&(n-=1),{value:t.slice(0,n),truncated:!0}}class s{constructor(){this.fetchObserver=null}start(t,e){this.eventCallback=t,this.networkConfig=e,this.observeFetch()}stop(){var t;null===(t=this.fetchObserver)||void 0===t||t.call(this),this.fetchObserver=null,this.eventCallback=void 0,this.networkConfig=void 0}notifyEvent(t){var e;null===(e=this.eventCallback)||void 0===e||e.call(this,t)}observeFetch(){const s=e();if(!s)return;const r=s.fetch;r&&(s.fetch=(e,s)=>t(this,void 0,void 0,function*(){var t,i;const a=Date.now(),c={timestamp:a,type:"fetch",method:(null==s?void 0:s.method)||"GET",url:e.toString(),requestHeaders:null==s?void 0:s.headers},l=null===(t=this.networkConfig)||void 0===t?void 0:t.body;if(null==l?void 0:l.request){const t=function(t){if(null!=t){if("string"==typeof t)return t;if(t instanceof URLSearchParams)return t.toString();if(t instanceof FormData){const e=[];return t.forEach((t,n)=>{e.push(`${n}=${"string"==typeof t?t:"[File]"}`)}),e.join("&")}}}(null==s?void 0:s.body);if(void 0!==t){const e=null!==(i=l.maxBodySizeBytes)&&void 0!==i?i:10240;c.requestBody=o(t,e).value}}try{const t=yield r(e,s),i=Date.now();c.status=t.status,c.duration=i-a;const u={};if(t.headers.forEach((t,e)=>{u[e]=t}),c.responseHeaders=u,null==l?void 0:l.response){if(function(t){return!!t&&n.some(e=>t.toLowerCase().startsWith(e))}(u["content-type"]||null))c.responseBodyStatus="skipped_binary",this.notifyEvent(c);else{t.clone().text().then(t=>{var e;const n=null!==(e=l.maxBodySizeBytes)&&void 0!==e?e:10240,{value:s,truncated:r}=o(t,n);c.responseBody=s,c.responseBodyStatus=r?"truncated":"captured",this.notifyEvent(c)},()=>{c.responseBodyStatus="error",this.notifyEvent(c)})}}else this.notifyEvent(c);return t}catch(t){const e=Date.now();c.duration=e-a;const n=t;throw c.error={name:n.name||"UnknownError",message:n.message||"An unknown error occurred"},this.notifyEvent(c),t}}),this.fetchObserver=()=>{s.fetch=r})}}export{s as NetworkObservers};
1
+ import{f as t,_ as e,a as n,c as r}from"./targeting-min.js";import{g as o}from"./index-min.js";function s(t){return"string"==typeof t||"number"==typeof t||"boolean"==typeof t||null==t}function i(t,e,n){t&&l({json:t,allowlist:e.map(a),excludelist:n.map(a),ancestors:[]})}function l(r){var o,i,a=r.json,c=r.targetObject,f=r.allowlist,h=r.excludelist,d=r.ancestors,v=r.parentObject,y=r.targetKey;c||(c=a);var p=Object.keys(c);try{for(var g=t(p),m=g.next();!m.done;m=g.next()){var b=m.value,w=e(e([],n(d),!1),[b],!1);s(c[b])?u(w,f)&&!u(w,h)||delete c[b]:l({json:a,targetObject:c[b],allowlist:f,excludelist:h,ancestors:w,parentObject:c,targetKey:b})}}catch(t){o={error:t}}finally{try{m&&!m.done&&(i=g.return)&&i.call(g)}finally{if(o)throw o.error}}0===Object.keys(c).length&&v&&y&&delete v[y]}function a(t){return t.startsWith("/")&&(t=t.slice(1)),t.split("/").map(function(t){return t.replace(/~0/g,"~").replace(/~1/g,"/")})}function c(t,e,n,r){if(void 0===n&&(n=0),void 0===r&&(r=0),r===e.length)return n===t.length;if(n===t.length){for(;r<e.length&&"**"===e[r];)r++;return r===e.length}var o=e[r];if("**"===o){if(r+1===e.length)return!0;for(var s=n;s<=t.length;s++)if(c(t,e,s,r+1))return!0;return!1}return("*"===o||o===t[n])&&c(t,e,n+1,r+1)}function u(t,e){return e.some(function(e){return c(t,e)})}const f=t=>void 0!==t&&("boolean"==typeof t?t:!1!==t.enabled),h=(t,e,n,r)=>{const{allowlist:o,excludelist:s}=(t=>{var e;return"object"==typeof t&&null!==t?{allowlist:null!==(e=t.allowlist)&&void 0!==e?e:[],excludelist:t.excludelist||t.blocklist||[]}:{allowlist:[],excludelist:[]}})(e),l=((t,e,n)=>{if(0===e.length&&0===n.length)return t;const r=e.length>0?e:["/**"];try{const e=JSON.parse(t);return i(e,r,n),JSON.stringify(e)}catch(e){return t}})(t,o,s);return r(l,n)},d=["image/","audio/","video/","application/octet-stream","font/"];function v(t,e){if(new Blob([t]).size<=e)return{value:t,truncated:!1};let n=0,r=Math.min(t.length,e);for(;n<r;){const o=Math.ceil((n+r)/2);new Blob([t.slice(0,o)]).size<=e?n=o:r=o-1}return n>0&&t.charCodeAt(n-1)>=55296&&t.charCodeAt(n-1)<=56319&&(n-=1),{value:t.slice(0,n),truncated:!0}}class y{constructor(){this.fetchObserver=null}start(t,e){this.eventCallback=t,this.networkConfig=e,this.observeFetch()}stop(){var t;null===(t=this.fetchObserver)||void 0===t||t.call(this),this.fetchObserver=null,this.eventCallback=void 0,this.networkConfig=void 0}notifyEvent(t){var e;null===(e=this.eventCallback)||void 0===e||e.call(this,t)}observeFetch(){const t=o();if(!t)return;const e=t.fetch;e&&(t.fetch=(t,n)=>r(this,void 0,void 0,function*(){var r,o;const s=Date.now(),i={timestamp:s,type:"fetch",method:(null==n?void 0:n.method)||"GET",url:t.toString(),requestHeaders:null==n?void 0:n.headers},l=null===(r=this.networkConfig)||void 0===r?void 0:r.body;if(l&&f(l.request)){const t=function(t){if(null!=t){if("string"==typeof t)return t;if(t instanceof URLSearchParams)return t.toString();if(t instanceof FormData){const e=[];return t.forEach((t,n)=>{e.push(`${n}=${"string"==typeof t?t:"[File]"}`)}),e.join("&")}}}(null==n?void 0:n.body);if(void 0!==t){const e=null!==(o=l.maxBodySizeBytes)&&void 0!==o?o:10240;i.requestBody=h(t,l.request,e,v).value}}try{const r=yield e(t,n),o=Date.now();i.status=r.status,i.duration=o-s;const a={};if(r.headers.forEach((t,e)=>{a[e]=t}),i.responseHeaders=a,l&&f(l.response)){if(function(t){return!!t&&d.some(e=>t.toLowerCase().startsWith(e))}(a["content-type"]||null))i.responseBodyStatus="skipped_binary",this.notifyEvent(i);else{r.clone().text().then(t=>{var e;const n=null!==(e=l.maxBodySizeBytes)&&void 0!==e?e:10240,{value:r,truncated:o}=h(t,l.response,n,v);i.responseBody=r,i.responseBodyStatus=o?"truncated":"captured",this.notifyEvent(i)},()=>{i.responseBodyStatus="error",this.notifyEvent(i)})}}else this.notifyEvent(i);return r}catch(t){const e=Date.now();i.duration=e-s;const n=t;throw i.error={name:n.name||"UnknownError",message:n.message||"An unknown error occurred"},this.notifyEvent(i),t}}),this.fetchObserver=()=>{t.fetch=e})}}export{y as NetworkObservers};
2
2
  //# sourceMappingURL=observers-min.js.map
Binary file
@@ -1 +1 @@
1
- {"version":3,"file":"observers-min.js","sources":["../../../src/observers.ts"],"sourcesContent":["import { getGlobalScope } from '@amplitude/analytics-core';\n\nexport type ResponseBodyStatus = 'captured' | 'truncated' | 'skipped_binary' | 'error';\n\nexport interface NetworkRequestEvent {\n timestamp: number;\n type: 'fetch';\n method: string;\n url: string;\n status?: number;\n duration?: number;\n requestHeaders?: Record<string, string>;\n responseHeaders?: Record<string, string>;\n requestBody?: string;\n responseBody?: string;\n responseBodyStatus?: ResponseBodyStatus;\n error?: {\n name: string;\n message: string;\n };\n}\n\nexport type NetworkEventCallback = (event: NetworkRequestEvent) => void;\n\nexport interface NetworkBodyConfig {\n request?: boolean;\n response?: boolean;\n maxBodySizeBytes?: number;\n}\n\nexport interface NetworkConfig {\n enabled: boolean;\n body?: NetworkBodyConfig;\n}\n\nconst DEFAULT_MAX_BODY_SIZE_BYTES = 10240; // 10KB\n\nconst BINARY_CONTENT_TYPE_PREFIXES = ['image/', 'audio/', 'video/', 'application/octet-stream', 'font/'];\n\nfunction isBinaryContentType(contentType: string | null): boolean {\n if (!contentType) return false;\n return BINARY_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.toLowerCase().startsWith(prefix));\n}\n\nfunction serializeRequestBody(body: BodyInit | null | undefined): string | undefined {\n if (body === null || body === undefined) return undefined;\n if (typeof body === 'string') return body;\n if (body instanceof URLSearchParams) return body.toString();\n if (body instanceof FormData) {\n const parts: string[] = [];\n body.forEach((value, key) => {\n parts.push(`${key}=${typeof value === 'string' ? value : '[File]'}`);\n });\n return parts.join('&');\n }\n // Blob, ArrayBuffer, ArrayBufferView, ReadableStream — skip\n return undefined;\n}\n\nfunction truncateToByteLimit(str: string, maxBytes: number): { value: string; truncated: boolean } {\n if (new Blob([str]).size <= maxBytes) {\n return { value: str, truncated: false };\n }\n // Binary search for the longest prefix whose UTF-8 byte length fits within maxBytes.\n // Cap hi at maxBytes since each UTF-8 character is at least 1 byte, so no more than\n // maxBytes characters can ever fit — this avoids large intermediate Blob allocations.\n let lo = 0;\n let hi = Math.min(str.length, maxBytes);\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (new Blob([str.slice(0, mid)]).size <= maxBytes) {\n lo = mid;\n } else {\n hi = mid - 1;\n }\n }\n // Avoid splitting a surrogate pair: if lo landed after a high surrogate, back up one position\n if (lo > 0 && str.charCodeAt(lo - 1) >= 0xd800 && str.charCodeAt(lo - 1) <= 0xdbff) {\n lo -= 1;\n }\n return { value: str.slice(0, lo), truncated: true };\n}\n\nexport class NetworkObservers {\n private fetchObserver: (() => void) | null = null;\n private eventCallback?: NetworkEventCallback;\n private networkConfig?: NetworkConfig;\n\n start(eventCallback: NetworkEventCallback, networkConfig?: NetworkConfig) {\n this.eventCallback = eventCallback;\n this.networkConfig = networkConfig;\n this.observeFetch();\n }\n\n stop() {\n this.fetchObserver?.();\n this.fetchObserver = null;\n this.eventCallback = undefined;\n this.networkConfig = undefined;\n }\n\n protected notifyEvent(event: NetworkRequestEvent) {\n this.eventCallback?.(event);\n }\n\n private observeFetch() {\n const globalScope = getGlobalScope();\n if (!globalScope) return;\n\n const originalFetch = globalScope.fetch;\n if (!originalFetch) return;\n\n globalScope.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {\n const startTime = Date.now();\n const requestEvent: NetworkRequestEvent = {\n timestamp: startTime,\n type: 'fetch',\n method: init?.method || 'GET', // Fetch API defaulted to GET when no method is provided\n url: input.toString(),\n requestHeaders: init?.headers as Record<string, string>,\n };\n\n // Capture request body if configured\n const bodyConfig = this.networkConfig?.body;\n if (bodyConfig?.request) {\n const serialized = serializeRequestBody(init?.body);\n if (serialized !== undefined) {\n const maxBytes = bodyConfig.maxBodySizeBytes ?? DEFAULT_MAX_BODY_SIZE_BYTES;\n requestEvent.requestBody = truncateToByteLimit(serialized, maxBytes).value;\n }\n }\n\n try {\n const response = await originalFetch(input, init);\n const endTime = Date.now();\n\n requestEvent.status = response.status;\n requestEvent.duration = endTime - startTime;\n\n // Convert Headers\n const headers: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headers[key] = value;\n });\n requestEvent.responseHeaders = headers;\n\n if (bodyConfig?.response) {\n const contentType = headers['content-type'] || null;\n if (isBinaryContentType(contentType)) {\n requestEvent.responseBodyStatus = 'skipped_binary';\n this.notifyEvent(requestEvent);\n } else {\n const cloned = response.clone();\n // Read body without blocking the response return to the caller\n cloned.text().then(\n (text) => {\n const maxBytes = bodyConfig.maxBodySizeBytes ?? DEFAULT_MAX_BODY_SIZE_BYTES;\n const { value, truncated } = truncateToByteLimit(text, maxBytes);\n requestEvent.responseBody = value;\n requestEvent.responseBodyStatus = truncated ? 'truncated' : 'captured';\n this.notifyEvent(requestEvent);\n },\n () => {\n requestEvent.responseBodyStatus = 'error';\n this.notifyEvent(requestEvent);\n },\n );\n }\n } else {\n this.notifyEvent(requestEvent);\n }\n\n return response;\n } catch (error) {\n const endTime = Date.now();\n requestEvent.duration = endTime - startTime;\n\n // Capture error information\n const typedError = error as Error;\n requestEvent.error = {\n name: typedError.name || 'UnknownError',\n message: typedError.message || 'An unknown error occurred',\n };\n\n this.notifyEvent(requestEvent);\n throw error;\n }\n };\n\n this.fetchObserver = () => {\n globalScope.fetch = originalFetch;\n };\n }\n}\n"],"names":["BINARY_CONTENT_TYPE_PREFIXES","truncateToByteLimit","str","maxBytes","Blob","size","value","truncated","lo","hi","Math","min","length","mid","ceil","slice","charCodeAt","NetworkObservers","constructor","this","fetchObserver","start","eventCallback","networkConfig","observeFetch","stop","_a","call","undefined","notifyEvent","event","globalScope","getGlobalScope","originalFetch","fetch","input","init","__awaiter","startTime","Date","now","requestEvent","timestamp","type","method","url","toString","requestHeaders","headers","bodyConfig","body","request","serialized","URLSearchParams","FormData","parts","forEach","key","push","join","serializeRequestBody","_b","maxBodySizeBytes","requestBody","response","endTime","status","duration","responseHeaders","contentType","some","prefix","toLowerCase","startsWith","isBinaryContentType","responseBodyStatus","clone","text","then","responseBody","error","typedError","name","message"],"mappings":"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"}
1
+ {"version":3,"file":"observers-min.js","sources":["../../../analytics-core/lib/esm/utils/json-query.js","../../../src/network-body-capture.ts","../../../src/observers.ts"],"sourcesContent":["import { __read, __spreadArray, __values } from \"tslib\";\nfunction isJsonPrimitive(json) {\n return (typeof json === 'string' ||\n typeof json === 'number' ||\n typeof json === 'boolean' ||\n json === null ||\n json === undefined);\n}\n/**\n * Prune a JSON object to only include the keys in the allowlist and excludes the keys\n * in the exclude list.\n *\n * This function is a mutative function that will modify the original JSON object.\n * This is done to avoid creating a new JSON object and copying the data.\n *\n * @param json - The JSON object to prune.\n * @param allowlist - The keys to include in the pruned JSON object.\n * @param excludelist - The keys to exclude from the pruned JSON object.\n */\nexport function pruneJson(json, allowlist, excludelist) {\n if (!json)\n return;\n // tokenize the allowlist and excludelist\n var allowlistTokens = allowlist.map(tokenizeJsonPath);\n var excludelistTokens = excludelist.map(tokenizeJsonPath);\n _pruneJson({\n json: json,\n allowlist: allowlistTokens,\n excludelist: excludelistTokens,\n ancestors: [],\n });\n}\nexport function _pruneJson(_a) {\n var e_1, _b;\n var json = _a.json, targetObject = _a.targetObject, allowlist = _a.allowlist, excludelist = _a.excludelist, ancestors = _a.ancestors, parentObject = _a.parentObject, targetKey = _a.targetKey;\n if (!targetObject) {\n targetObject = json;\n }\n var keys = Object.keys(targetObject);\n try {\n for (var keys_1 = __values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {\n var key = keys_1_1.value;\n var path = __spreadArray(__spreadArray([], __read(ancestors), false), [key], false);\n if (isJsonPrimitive(targetObject[key])) {\n // if the value does not match allowlist or matches exclude list, delete it\n if (!hasPathMatchInList(path, allowlist) || hasPathMatchInList(path, excludelist)) {\n delete targetObject[key];\n }\n }\n else {\n _pruneJson({\n json: json,\n targetObject: targetObject[key],\n allowlist: allowlist,\n excludelist: excludelist,\n ancestors: path,\n parentObject: targetObject,\n targetKey: key,\n });\n }\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (keys_1_1 && !keys_1_1.done && (_b = keys_1.return)) _b.call(keys_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n // if this object is empty now, delete the whole object\n if (Object.keys(targetObject).length === 0 && parentObject && targetKey) {\n delete parentObject[targetKey];\n }\n}\n/**\n * Tokenize a JSON path string into an array of strings.\n * Escapes ~0 and ~1 to ~ and / respectively.\n *\n * e.g.) turns string \"a/b/c\" into [\"a\", \"b\", \"c\"]\n *\n * @param path - The JSON path to tokenize.\n * @returns The tokenized JSON path.\n */\nexport function tokenizeJsonPath(path) {\n if (path.startsWith('/')) {\n path = path.slice(1);\n }\n return path.split('/').map(function (token) { return token.replace(/~0/g, '~').replace(/~1/g, '/'); });\n}\n/**\n * Check if a JSON path matches a path matcher.\n *\n * Rules:\n * 1. If a key in a path and a matcher are the same, then they match, move to the next\n * 2. If the matcher is a *, then it matches the key, move to the next\n * 3. If the matcher is a **, then it matches >=0 keys\n *\n * @param path - The path to check.\n * @param pathMatcher - The path matcher to check against.\n * @param i - The current index of the path.\n * @param j - The current index of the path matcher.\n * @returns True if the path matches the path matcher, false otherwise.\n */\nexport function isPathMatch(path, pathMatcher, i, j) {\n if (i === void 0) { i = 0; }\n if (j === void 0) { j = 0; }\n if (j === pathMatcher.length) {\n return i === path.length;\n }\n if (i === path.length) {\n while (j < pathMatcher.length && pathMatcher[j] === '**') {\n j++;\n }\n return j === pathMatcher.length;\n }\n var currentMatcher = pathMatcher[j];\n if (currentMatcher === '**') {\n if (j + 1 === pathMatcher.length) {\n return true;\n }\n for (var k = i; k <= path.length; k++) {\n if (isPathMatch(path, pathMatcher, k, j + 1)) {\n return true;\n }\n }\n return false;\n }\n else if (currentMatcher === '*' || currentMatcher === path[i]) {\n return isPathMatch(path, pathMatcher, i + 1, j + 1);\n }\n else {\n return false;\n }\n}\n/**\n * Check if a JSON path matches any of the path matchers in the allow or exclude list.\n *\n * @param path - The JSON path to check.\n * @param allowOrExcludeList - The allow or exclude list to check against.\n * @returns True if the path matches any of the path matchers in the allow or exclude list, false otherwise.\n */\nfunction hasPathMatchInList(path, allowOrExcludeList) {\n return allowOrExcludeList.some(function (l) { return isPathMatch(path, l); });\n}\n//# sourceMappingURL=json-query.js.map","import { pruneJson } from '@amplitude/analytics-core';\n\nexport type BodyCaptureRuleConfig =\n | boolean\n | {\n enabled?: boolean;\n allowlist?: string[];\n /** @deprecated use excludelist */\n blocklist?: string[];\n excludelist?: string[];\n };\n\nexport const isBodyCaptureEnabled = (config: BodyCaptureRuleConfig | undefined): boolean => {\n if (config === undefined) {\n return false;\n }\n if (typeof config === 'boolean') {\n return config;\n }\n return config.enabled !== false;\n};\n\nexport const getBodyMaskingLists = (\n config: BodyCaptureRuleConfig | undefined,\n): { allowlist: string[]; excludelist: string[] } => {\n if (typeof config === 'object' && config !== null) {\n return {\n allowlist: config.allowlist ?? [],\n excludelist: config.excludelist || config.blocklist || [],\n };\n }\n return { allowlist: [], excludelist: [] };\n};\n\nexport const applyBodyMasking = (serialized: string, allowlist: string[], excludelist: string[]): string => {\n if (allowlist.length === 0 && excludelist.length === 0) {\n return serialized;\n }\n\n const effectiveAllowlist = allowlist.length > 0 ? allowlist : ['/**'];\n\n try {\n const json = JSON.parse(serialized) as Record<string, unknown>;\n pruneJson(json, effectiveAllowlist, excludelist);\n return JSON.stringify(json);\n } catch {\n return serialized;\n }\n};\n\nexport const captureSerializedBody = (\n serialized: string,\n config: BodyCaptureRuleConfig | undefined,\n maxBytes: number,\n truncate: (value: string, max: number) => { value: string; truncated: boolean },\n): { value: string; truncated: boolean } => {\n const { allowlist, excludelist } = getBodyMaskingLists(config);\n const masked = applyBodyMasking(serialized, allowlist, excludelist);\n return truncate(masked, maxBytes);\n};\n","import { getGlobalScope } from '@amplitude/analytics-core';\n\nimport { type BodyCaptureRuleConfig, captureSerializedBody, isBodyCaptureEnabled } from './network-body-capture';\n\nexport type ResponseBodyStatus = 'captured' | 'truncated' | 'skipped_binary' | 'error';\n\nexport interface NetworkRequestEvent {\n timestamp: number;\n type: 'fetch';\n method: string;\n url: string;\n status?: number;\n duration?: number;\n requestHeaders?: Record<string, string>;\n responseHeaders?: Record<string, string>;\n requestBody?: string;\n responseBody?: string;\n responseBodyStatus?: ResponseBodyStatus;\n error?: {\n name: string;\n message: string;\n };\n}\n\nexport type NetworkEventCallback = (event: NetworkRequestEvent) => void;\n\nexport interface NetworkBodyConfig {\n request?: BodyCaptureRuleConfig;\n response?: BodyCaptureRuleConfig;\n maxBodySizeBytes?: number;\n}\n\nexport interface NetworkConfig {\n enabled: boolean;\n body?: NetworkBodyConfig;\n}\n\nconst DEFAULT_MAX_BODY_SIZE_BYTES = 10240; // 10KB\n\nconst BINARY_CONTENT_TYPE_PREFIXES = ['image/', 'audio/', 'video/', 'application/octet-stream', 'font/'];\n\nfunction isBinaryContentType(contentType: string | null): boolean {\n if (!contentType) return false;\n return BINARY_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.toLowerCase().startsWith(prefix));\n}\n\nfunction serializeRequestBody(body: BodyInit | null | undefined): string | undefined {\n if (body === null || body === undefined) return undefined;\n if (typeof body === 'string') return body;\n if (body instanceof URLSearchParams) return body.toString();\n if (body instanceof FormData) {\n const parts: string[] = [];\n body.forEach((value, key) => {\n parts.push(`${key}=${typeof value === 'string' ? value : '[File]'}`);\n });\n return parts.join('&');\n }\n // Blob, ArrayBuffer, ArrayBufferView, ReadableStream — skip\n return undefined;\n}\n\nfunction truncateToByteLimit(str: string, maxBytes: number): { value: string; truncated: boolean } {\n if (new Blob([str]).size <= maxBytes) {\n return { value: str, truncated: false };\n }\n // Binary search for the longest prefix whose UTF-8 byte length fits within maxBytes.\n // Cap hi at maxBytes since each UTF-8 character is at least 1 byte, so no more than\n // maxBytes characters can ever fit — this avoids large intermediate Blob allocations.\n let lo = 0;\n let hi = Math.min(str.length, maxBytes);\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (new Blob([str.slice(0, mid)]).size <= maxBytes) {\n lo = mid;\n } else {\n hi = mid - 1;\n }\n }\n // Avoid splitting a surrogate pair: if lo landed after a high surrogate, back up one position\n if (lo > 0 && str.charCodeAt(lo - 1) >= 0xd800 && str.charCodeAt(lo - 1) <= 0xdbff) {\n lo -= 1;\n }\n return { value: str.slice(0, lo), truncated: true };\n}\n\nexport class NetworkObservers {\n private fetchObserver: (() => void) | null = null;\n private eventCallback?: NetworkEventCallback;\n private networkConfig?: NetworkConfig;\n\n start(eventCallback: NetworkEventCallback, networkConfig?: NetworkConfig) {\n this.eventCallback = eventCallback;\n this.networkConfig = networkConfig;\n this.observeFetch();\n }\n\n stop() {\n this.fetchObserver?.();\n this.fetchObserver = null;\n this.eventCallback = undefined;\n this.networkConfig = undefined;\n }\n\n protected notifyEvent(event: NetworkRequestEvent) {\n this.eventCallback?.(event);\n }\n\n private observeFetch() {\n const globalScope = getGlobalScope();\n if (!globalScope) return;\n\n const originalFetch = globalScope.fetch;\n if (!originalFetch) return;\n\n globalScope.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {\n const startTime = Date.now();\n const requestEvent: NetworkRequestEvent = {\n timestamp: startTime,\n type: 'fetch',\n method: init?.method || 'GET', // Fetch API defaulted to GET when no method is provided\n url: input.toString(),\n requestHeaders: init?.headers as Record<string, string>,\n };\n\n // Capture request body if configured\n const bodyConfig = this.networkConfig?.body;\n if (bodyConfig && isBodyCaptureEnabled(bodyConfig.request)) {\n const serialized = serializeRequestBody(init?.body);\n if (serialized !== undefined) {\n const maxBytes = bodyConfig.maxBodySizeBytes ?? DEFAULT_MAX_BODY_SIZE_BYTES;\n requestEvent.requestBody = captureSerializedBody(\n serialized,\n bodyConfig.request,\n maxBytes,\n truncateToByteLimit,\n ).value;\n }\n }\n\n try {\n const response = await originalFetch(input, init);\n const endTime = Date.now();\n\n requestEvent.status = response.status;\n requestEvent.duration = endTime - startTime;\n\n // Convert Headers\n const headers: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headers[key] = value;\n });\n requestEvent.responseHeaders = headers;\n\n if (bodyConfig && isBodyCaptureEnabled(bodyConfig.response)) {\n const contentType = headers['content-type'] || null;\n if (isBinaryContentType(contentType)) {\n requestEvent.responseBodyStatus = 'skipped_binary';\n this.notifyEvent(requestEvent);\n } else {\n const cloned = response.clone();\n // Read body without blocking the response return to the caller\n cloned.text().then(\n (text) => {\n const maxBytes = bodyConfig.maxBodySizeBytes ?? DEFAULT_MAX_BODY_SIZE_BYTES;\n const { value, truncated } = captureSerializedBody(\n text,\n bodyConfig.response,\n maxBytes,\n truncateToByteLimit,\n );\n requestEvent.responseBody = value;\n requestEvent.responseBodyStatus = truncated ? 'truncated' : 'captured';\n this.notifyEvent(requestEvent);\n },\n () => {\n requestEvent.responseBodyStatus = 'error';\n this.notifyEvent(requestEvent);\n },\n );\n }\n } else {\n this.notifyEvent(requestEvent);\n }\n\n return response;\n } catch (error) {\n const endTime = Date.now();\n requestEvent.duration = endTime - startTime;\n\n // Capture error information\n const typedError = error as Error;\n requestEvent.error = {\n name: typedError.name || 'UnknownError',\n message: typedError.message || 'An unknown error occurred',\n };\n\n this.notifyEvent(requestEvent);\n throw error;\n }\n };\n\n this.fetchObserver = () => {\n globalScope.fetch = originalFetch;\n };\n }\n}\n"],"names":["isJsonPrimitive","json","pruneJson","allowlist","excludelist","_pruneJson","map","tokenizeJsonPath","ancestors","_a","e_1","_b","targetObject","parentObject","targetKey","keys","Object","keys_1","__values","keys_1_1","next","done","key","value","path","__spreadArray","__read","hasPathMatchInList","e_1_1","error","return","call","length","startsWith","slice","split","token","replace","isPathMatch","pathMatcher","i","j","currentMatcher","k","allowOrExcludeList","some","l","isBodyCaptureEnabled","config","undefined","enabled","captureSerializedBody","serialized","maxBytes","truncate","blocklist","getBodyMaskingLists","masked","effectiveAllowlist","JSON","parse","stringify","applyBodyMasking","BINARY_CONTENT_TYPE_PREFIXES","truncateToByteLimit","str","Blob","size","truncated","lo","hi","Math","min","mid","ceil","charCodeAt","NetworkObservers","constructor","this","fetchObserver","start","eventCallback","networkConfig","observeFetch","stop","notifyEvent","event","globalScope","getGlobalScope","originalFetch","fetch","input","init","__awaiter","startTime","Date","now","requestEvent","timestamp","type","method","url","toString","requestHeaders","headers","bodyConfig","body","request","URLSearchParams","FormData","parts","forEach","push","join","serializeRequestBody","maxBodySizeBytes","requestBody","response","endTime","status","duration","responseHeaders","contentType","prefix","toLowerCase","isBinaryContentType","responseBodyStatus","clone","text","then","responseBody","typedError","name","message"],"mappings":"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"}