@stainlessdev/xray-core 0.5.1-dev.6191ec4 → 0.6.0-branch.bg-fix-req-id-gen.e29953f

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal.ts","../src/state.ts","../src/limited_buffer.ts","../src/headers.ts","../src/websocket.ts","../src/encoding.ts","../src/request_log.ts","../src/logger.ts"],"sourcesContent":["import type { CaptureConfig, RedactionConfig } from './config';\nimport type { XrayContext } from './types';\nimport { bindObject, getContextFromObject, getContextState } from './state';\n\nexport { LimitedBuffer } from './limited_buffer';\nexport {\n headerValuesFromFetchHeaders,\n headerValuesFromFetchHeadersWithLimit,\n headerValuesFromNodeHeaders,\n headerTokenList,\n} from './headers';\nexport { isWebsocketUpgrade, isWebsocketUpgradeFetch } from './websocket';\nexport { makeCapturedBody } from './request_log';\nexport { logWithLevel } from './logger';\n\nexport function bindContextToObject(target: object, ctx: XrayContext): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n bindObject(target, state);\n}\n\nexport function getXrayContextFromObject(target: unknown): XrayContext | undefined {\n return getContextFromObject(target);\n}\n\nexport function setContextRoute(ctx: XrayContext, route: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n const normalized =\n state.config.route.normalize && state.config.route.normalizer\n ? state.config.route.normalizer(route)\n : route;\n state.request.route = normalized;\n}\n\nexport function setContextRequestId(ctx: XrayContext, requestId: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n state.request.requestId = requestId;\n state.context.requestId = requestId;\n}\n\nexport function setCaptureOverride(\n ctx: XrayContext,\n capture: Partial<CaptureConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !capture) {\n return;\n }\n state.captureOverride = capture;\n}\n\nexport function setRedactionOverride(\n ctx: XrayContext,\n redaction: Partial<RedactionConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !redaction) {\n return;\n }\n state.redactionOverride = redaction;\n}\n","import type { Span } from '@opentelemetry/api';\nimport type { AttributeValue, NormalizedRequest, XrayContext } from './types';\nimport type { CaptureConfig, RedactionConfig, ResolvedXrayConfig } from './config';\n\nexport type RequestState = {\n request: NormalizedRequest;\n config: ResolvedXrayConfig;\n span?: Span;\n context: XrayContext;\n attributes: Record<string, AttributeValue>;\n events: Array<{ name: string; attributes?: Record<string, AttributeValue> }>;\n userId?: string;\n sessionId?: string;\n error?: unknown;\n captureOverride?: Partial<CaptureConfig>;\n redactionOverride?: Partial<RedactionConfig>;\n};\n\nconst contextMap = new WeakMap<XrayContext, RequestState>();\nconst objectMap = new WeakMap<object, RequestState>();\n\nexport function bindContext(ctx: XrayContext, state: RequestState): void {\n contextMap.set(ctx, state);\n}\n\nexport function getContextState(ctx: XrayContext): RequestState | undefined {\n return contextMap.get(ctx);\n}\n\nexport function bindObject(target: object, state: RequestState): void {\n objectMap.set(target, state);\n}\n\nexport function getContextFromObject(target: unknown): XrayContext | undefined {\n const state = getStateFromObject(target);\n return state?.context;\n}\n\nexport function getStateFromObject(target: unknown): RequestState | undefined {\n if (!target || typeof target !== 'object') {\n return undefined;\n }\n if (objectMap.has(target)) {\n return objectMap.get(target);\n }\n\n const fallback = findNestedTarget(target as Record<string, unknown>);\n if (fallback && objectMap.has(fallback)) {\n return objectMap.get(fallback);\n }\n return undefined;\n}\n\nfunction findNestedTarget(obj: Record<string, unknown>): object | null {\n if (obj.raw && typeof obj.raw === 'object') {\n return obj.raw as object;\n }\n if (obj.req && typeof obj.req === 'object') {\n const req = obj.req as Record<string, unknown>;\n if (req.raw && typeof req.raw === 'object') {\n return req.raw as object;\n }\n return req as object;\n }\n if (obj.request && typeof obj.request === 'object') {\n const request = obj.request as Record<string, unknown>;\n if (request.raw && typeof request.raw === 'object') {\n return request.raw as object;\n }\n return request as object;\n }\n return null;\n}\n","export class LimitedBuffer {\n private buffer: Uint8Array;\n private length: number;\n private readonly limit: number;\n private truncatedFlag: boolean;\n private total: number;\n\n constructor(limit: number) {\n const normalized = Number.isFinite(limit) ? Math.max(0, limit) : 0;\n const initialCap = Math.min(normalized, 32 * 1024);\n this.buffer = new Uint8Array(initialCap);\n this.length = 0;\n this.limit = normalized;\n this.truncatedFlag = false;\n this.total = 0;\n }\n\n bytes(): Uint8Array {\n return this.buffer.slice(0, this.length);\n }\n\n capturedBytes(): number {\n return this.length;\n }\n\n totalBytes(): number {\n return this.total;\n }\n\n truncated(): boolean {\n return this.truncatedFlag;\n }\n\n write(chunk: Uint8Array): void {\n if (!chunk || chunk.length === 0) {\n return;\n }\n\n this.total += chunk.length;\n if (this.limit <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const remaining = this.limit - this.length;\n if (remaining <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const toCopy = Math.min(remaining, chunk.length);\n this.ensureCapacity(this.length + toCopy);\n this.buffer.set(chunk.subarray(0, toCopy), this.length);\n this.length += toCopy;\n if (toCopy < chunk.length) {\n this.truncatedFlag = true;\n }\n }\n\n private ensureCapacity(size: number): void {\n if (this.buffer.length >= size) {\n return;\n }\n\n let nextSize = this.buffer.length;\n if (nextSize === 0) {\n nextSize = 1;\n }\n while (nextSize < size) {\n nextSize *= 2;\n }\n if (nextSize > this.limit) {\n nextSize = this.limit;\n }\n const next = new Uint8Array(nextSize);\n next.set(this.buffer.subarray(0, this.length));\n this.buffer = next;\n }\n}\n","export type HeaderCapture = {\n headers: Record<string, string | string[]>;\n truncated: boolean;\n};\n\nexport function headerValuesFromNodeHeaders(\n headers: Record<string, string | string[] | number | undefined>,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value == null) {\n continue;\n }\n const name = key.trim();\n if (!name) {\n continue;\n }\n if (Array.isArray(value)) {\n const entries = value.map((item) => `${item}`);\n if (entries.length > 0) {\n result[name] = entries.length === 1 ? entries[0]! : entries;\n }\n } else {\n result[name] = `${value}`;\n }\n }\n return Object.keys(result).length === 0 ? {} : result;\n}\n\nexport function headerValuesFromFetchHeaders(headers: Headers): Record<string, string | string[]> {\n return headerValuesFromFetchHeadersWithLimit(headers, Number.POSITIVE_INFINITY).headers;\n}\n\nexport function headerValuesFromFetchHeadersWithLimit(\n headers: Headers,\n maxBytes: number,\n): HeaderCapture {\n const result: Record<string, string | string[]> = {};\n let truncated = false;\n let remaining = Number.isFinite(maxBytes) ? Math.max(0, maxBytes) : Number.POSITIVE_INFINITY;\n const setCookie = getSetCookie(headers);\n if (setCookie) {\n const values = takeHeaderValues('set-cookie', setCookie, remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result['set-cookie'] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n }\n\n headers.forEach((value, key) => {\n const name = key.trim();\n if (!name) {\n return;\n }\n if (name.toLowerCase() === 'set-cookie' && setCookie) {\n return;\n }\n const values = takeHeaderValues(name, [value], remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result[name] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n });\n\n return {\n headers: Object.keys(result).length === 0 ? {} : result,\n truncated,\n };\n}\n\nexport function headerTokenList(values: string[] | string | undefined): string[] {\n if (!values) {\n return [];\n }\n if (Array.isArray(values)) {\n return splitTokens(values);\n }\n return splitTokens([values]);\n}\n\nfunction splitTokens(values: string[]): string[] {\n const tokens: string[] = [];\n for (const value of values) {\n if (!value) {\n continue;\n }\n for (const part of value.split(',')) {\n const trimmed = part.trim();\n if (trimmed) {\n tokens.push(trimmed);\n }\n }\n }\n return tokens;\n}\n\nfunction getSetCookie(headers: Headers): string[] | null {\n const maybe = headers as Headers & { getSetCookie?: () => string[] };\n if (typeof maybe.getSetCookie === 'function') {\n const values = maybe.getSetCookie();\n return values.length > 0 ? values : null;\n }\n return null;\n}\n\nfunction takeHeaderValues(\n name: string,\n values: string[],\n remaining: number,\n): { values: string[]; remaining: number; truncated: boolean } {\n if (remaining <= 0) {\n return { remaining: 0, truncated: true, values: [] };\n }\n\n const taken: string[] = [];\n let used = 0;\n for (const value of values) {\n if (!value) {\n continue;\n }\n const size = name.length + value.length;\n if (used + size > remaining) {\n return { remaining: Math.max(0, remaining - used), truncated: true, values: taken };\n }\n used += size;\n taken.push(value);\n }\n\n return { remaining: Math.max(0, remaining - used), truncated: false, values: taken };\n}\n","import { headerTokenList } from './headers';\n\ntype HeaderValues = Record<string, string | string[]>;\n\nexport function isWebsocketUpgrade(\n statusCode: number,\n requestHeaders: HeaderValues | undefined,\n responseHeaders: HeaderValues | undefined,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasToken(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasToken(requestHeaders, 'upgrade', 'websocket');\n}\n\nexport function isWebsocketUpgradeFetch(\n statusCode: number,\n requestHeaders: Headers,\n responseHeaders: Headers,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasTokenFetch(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasTokenFetch(requestHeaders, 'upgrade', 'websocket');\n}\n\nfunction headerHasToken(headers: HeaderValues | undefined, name: string, token: string): boolean {\n if (!headers) {\n return false;\n }\n const values = headers[name] ?? headers[name.toLowerCase()] ?? headers[name.toUpperCase()];\n if (!values) {\n return false;\n }\n const tokens = headerTokenList(values);\n return tokens.some((value) => value.toLowerCase() === token.toLowerCase());\n}\n\nfunction headerHasTokenFetch(headers: Headers, name: string, token: string): boolean {\n const value = headers.get(name);\n if (!value) {\n return false;\n }\n return value.split(',').some((part) => part.trim().toLowerCase() === token.toLowerCase());\n}\n","const utf8Decoder =\n typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { fatal: true }) : null;\nconst utf8DecoderLenient = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8') : null;\nconst maybeBuffer = (\n globalThis as typeof globalThis & {\n Buffer?: { from(data: Uint8Array): { toString(encoding?: string): string } };\n }\n).Buffer;\n\nexport function encodeBase64(bytes: Uint8Array): string {\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('base64');\n }\n let binary = '';\n for (let i = 0; i < bytes.length; i += 1) {\n const byte = bytes[i];\n if (byte === undefined) {\n continue;\n }\n binary += String.fromCharCode(byte);\n }\n if (typeof btoa !== 'undefined') {\n return btoa(binary);\n }\n return '';\n}\n\nexport function isValidUtf8(bytes: Uint8Array): boolean {\n if (!utf8Decoder) {\n return false;\n }\n try {\n utf8Decoder.decode(bytes);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function decodeUtf8(bytes: Uint8Array): string {\n if (utf8DecoderLenient) {\n return utf8DecoderLenient.decode(bytes);\n }\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('utf8');\n }\n return '';\n}\n","import type { CapturedBody } from './types';\nimport { decodeUtf8, encodeBase64, isValidUtf8 } from './encoding';\n\n// eslint-disable-next-line no-control-regex\nconst controlChars = /[\\x00-\\x1F\\x7F]/g;\n\nexport function sanitizeLogString(value: string): string {\n if (!value) {\n return value;\n }\n return value.replace(controlChars, '');\n}\n\nexport function sanitizeHeaderValues(\n headers: Record<string, string | string[]> | undefined,\n): Record<string, string | string[]> | undefined {\n if (!headers) {\n return undefined;\n }\n\n const sanitized: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n const name = sanitizeLogString(key);\n if (Array.isArray(value)) {\n sanitized[name] = value.map((entry) => sanitizeLogString(entry));\n } else {\n sanitized[name] = sanitizeLogString(value);\n }\n }\n return sanitized;\n}\n\nexport function makeCapturedBody(\n bytes: Uint8Array | undefined,\n totalBytes: number,\n truncated: boolean,\n mode: 'text' | 'base64',\n): CapturedBody | undefined {\n if (!bytes) {\n return undefined;\n }\n\n if (mode === 'base64') {\n return {\n bytes: totalBytes,\n encoding: 'base64',\n truncated,\n value: encodeBase64(bytes),\n };\n }\n\n if (isValidUtf8(bytes)) {\n return {\n bytes: totalBytes,\n encoding: 'utf8',\n truncated,\n value: decodeUtf8(bytes),\n };\n }\n\n return {\n bytes: totalBytes,\n encoding: 'base64',\n truncated,\n value: encodeBase64(bytes),\n };\n}\n","import type { Logger, LogLevel } from './types';\n\nconst logLevelOrder: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nexport function logWithLevel(\n logger: Logger,\n level: LogLevel,\n threshold: LogLevel,\n message: string,\n fields?: Record<string, unknown>,\n): void {\n if (logLevelOrder[level] < logLevelOrder[threshold]) {\n return;\n }\n\n const fn =\n logger[level] ?? logger.warn ?? logger.info ?? logger.debug ?? logger.error ?? console.log;\n\n try {\n fn.call(logger, message, fields);\n } catch {\n // Logging should never disrupt instrumentation.\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/internal.ts","../src/state.ts","../src/limited_buffer.ts","../src/headers.ts","../src/websocket.ts","../src/encoding.ts","../src/request_log.ts","../src/logger.ts","../src/uuid.ts"],"sourcesContent":["import type { CaptureConfig, RedactionConfig } from './config';\nimport type { XrayContext } from './types';\nimport { bindObject, getContextFromObject, getContextState } from './state';\n\nexport { LimitedBuffer } from './limited_buffer';\nexport {\n headerValuesFromFetchHeaders,\n headerValuesFromFetchHeadersWithLimit,\n headerValuesFromNodeHeaders,\n headerTokenList,\n} from './headers';\nexport { isWebsocketUpgrade, isWebsocketUpgradeFetch } from './websocket';\nexport { makeCapturedBody } from './request_log';\nexport { logWithLevel } from './logger';\nexport { uuidv7 } from './uuid';\n\nexport function bindContextToObject(target: object, ctx: XrayContext): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n bindObject(target, state);\n}\n\nexport function getXrayContextFromObject(target: unknown): XrayContext | undefined {\n return getContextFromObject(target);\n}\n\nexport function setContextRoute(ctx: XrayContext, route: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n const normalized =\n state.config.route.normalize && state.config.route.normalizer\n ? state.config.route.normalizer(route)\n : route;\n state.request.route = normalized;\n}\n\nexport function setContextRequestId(ctx: XrayContext, requestId: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n state.request.requestId = requestId;\n state.context.requestId = requestId;\n}\n\nexport function setCaptureOverride(\n ctx: XrayContext,\n capture: Partial<CaptureConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !capture) {\n return;\n }\n state.captureOverride = capture;\n}\n\nexport function setRedactionOverride(\n ctx: XrayContext,\n redaction: Partial<RedactionConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !redaction) {\n return;\n }\n state.redactionOverride = redaction;\n}\n","import type { Span } from '@opentelemetry/api';\nimport type { AttributeValue, NormalizedRequest, XrayContext } from './types';\nimport type { CaptureConfig, RedactionConfig, ResolvedXrayConfig } from './config';\n\nexport type RequestState = {\n request: NormalizedRequest;\n config: ResolvedXrayConfig;\n span?: Span;\n context: XrayContext;\n attributes: Record<string, AttributeValue>;\n events: Array<{ name: string; attributes?: Record<string, AttributeValue> }>;\n userId?: string;\n sessionId?: string;\n error?: unknown;\n captureOverride?: Partial<CaptureConfig>;\n redactionOverride?: Partial<RedactionConfig>;\n};\n\nconst contextMap = new WeakMap<XrayContext, RequestState>();\nconst objectMap = new WeakMap<object, RequestState>();\n\nexport function bindContext(ctx: XrayContext, state: RequestState): void {\n contextMap.set(ctx, state);\n}\n\nexport function getContextState(ctx: XrayContext): RequestState | undefined {\n return contextMap.get(ctx);\n}\n\nexport function bindObject(target: object, state: RequestState): void {\n objectMap.set(target, state);\n}\n\nexport function getContextFromObject(target: unknown): XrayContext | undefined {\n const state = getStateFromObject(target);\n return state?.context;\n}\n\nexport function getStateFromObject(target: unknown): RequestState | undefined {\n if (!target || typeof target !== 'object') {\n return undefined;\n }\n if (objectMap.has(target)) {\n return objectMap.get(target);\n }\n\n const fallback = findNestedTarget(target as Record<string, unknown>);\n if (fallback && objectMap.has(fallback)) {\n return objectMap.get(fallback);\n }\n return undefined;\n}\n\nfunction findNestedTarget(obj: Record<string, unknown>): object | null {\n if (obj.raw && typeof obj.raw === 'object') {\n return obj.raw as object;\n }\n if (obj.req && typeof obj.req === 'object') {\n const req = obj.req as Record<string, unknown>;\n if (req.raw && typeof req.raw === 'object') {\n return req.raw as object;\n }\n return req as object;\n }\n if (obj.request && typeof obj.request === 'object') {\n const request = obj.request as Record<string, unknown>;\n if (request.raw && typeof request.raw === 'object') {\n return request.raw as object;\n }\n return request as object;\n }\n return null;\n}\n","export class LimitedBuffer {\n private buffer: Uint8Array;\n private length: number;\n private readonly limit: number;\n private truncatedFlag: boolean;\n private total: number;\n\n constructor(limit: number) {\n const normalized = Number.isFinite(limit) ? Math.max(0, limit) : 0;\n const initialCap = Math.min(normalized, 32 * 1024);\n this.buffer = new Uint8Array(initialCap);\n this.length = 0;\n this.limit = normalized;\n this.truncatedFlag = false;\n this.total = 0;\n }\n\n bytes(): Uint8Array {\n return this.buffer.slice(0, this.length);\n }\n\n capturedBytes(): number {\n return this.length;\n }\n\n totalBytes(): number {\n return this.total;\n }\n\n truncated(): boolean {\n return this.truncatedFlag;\n }\n\n write(chunk: Uint8Array): void {\n if (!chunk || chunk.length === 0) {\n return;\n }\n\n this.total += chunk.length;\n if (this.limit <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const remaining = this.limit - this.length;\n if (remaining <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const toCopy = Math.min(remaining, chunk.length);\n this.ensureCapacity(this.length + toCopy);\n this.buffer.set(chunk.subarray(0, toCopy), this.length);\n this.length += toCopy;\n if (toCopy < chunk.length) {\n this.truncatedFlag = true;\n }\n }\n\n private ensureCapacity(size: number): void {\n if (this.buffer.length >= size) {\n return;\n }\n\n let nextSize = this.buffer.length;\n if (nextSize === 0) {\n nextSize = 1;\n }\n while (nextSize < size) {\n nextSize *= 2;\n }\n if (nextSize > this.limit) {\n nextSize = this.limit;\n }\n const next = new Uint8Array(nextSize);\n next.set(this.buffer.subarray(0, this.length));\n this.buffer = next;\n }\n}\n","export type HeaderCapture = {\n headers: Record<string, string | string[]>;\n truncated: boolean;\n};\n\nexport function headerValuesFromNodeHeaders(\n headers: Record<string, string | string[] | number | undefined>,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value == null) {\n continue;\n }\n const name = key.trim();\n if (!name) {\n continue;\n }\n if (Array.isArray(value)) {\n const entries = value.map((item) => `${item}`);\n if (entries.length > 0) {\n result[name] = entries.length === 1 ? entries[0]! : entries;\n }\n } else {\n result[name] = `${value}`;\n }\n }\n return Object.keys(result).length === 0 ? {} : result;\n}\n\nexport function headerValuesFromFetchHeaders(headers: Headers): Record<string, string | string[]> {\n return headerValuesFromFetchHeadersWithLimit(headers, Number.POSITIVE_INFINITY).headers;\n}\n\nexport function headerValuesFromFetchHeadersWithLimit(\n headers: Headers,\n maxBytes: number,\n): HeaderCapture {\n const result: Record<string, string | string[]> = {};\n let truncated = false;\n let remaining = Number.isFinite(maxBytes) ? Math.max(0, maxBytes) : Number.POSITIVE_INFINITY;\n const setCookie = getSetCookie(headers);\n if (setCookie) {\n const values = takeHeaderValues('set-cookie', setCookie, remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result['set-cookie'] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n }\n\n headers.forEach((value, key) => {\n const name = key.trim();\n if (!name) {\n return;\n }\n if (name.toLowerCase() === 'set-cookie' && setCookie) {\n return;\n }\n const values = takeHeaderValues(name, [value], remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result[name] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n });\n\n return {\n headers: Object.keys(result).length === 0 ? {} : result,\n truncated,\n };\n}\n\nexport function headerTokenList(values: string[] | string | undefined): string[] {\n if (!values) {\n return [];\n }\n if (Array.isArray(values)) {\n return splitTokens(values);\n }\n return splitTokens([values]);\n}\n\nfunction splitTokens(values: string[]): string[] {\n const tokens: string[] = [];\n for (const value of values) {\n if (!value) {\n continue;\n }\n for (const part of value.split(',')) {\n const trimmed = part.trim();\n if (trimmed) {\n tokens.push(trimmed);\n }\n }\n }\n return tokens;\n}\n\nfunction getSetCookie(headers: Headers): string[] | null {\n const maybe = headers as Headers & { getSetCookie?: () => string[] };\n if (typeof maybe.getSetCookie === 'function') {\n const values = maybe.getSetCookie();\n return values.length > 0 ? values : null;\n }\n return null;\n}\n\nfunction takeHeaderValues(\n name: string,\n values: string[],\n remaining: number,\n): { values: string[]; remaining: number; truncated: boolean } {\n if (remaining <= 0) {\n return { remaining: 0, truncated: true, values: [] };\n }\n\n const taken: string[] = [];\n let used = 0;\n for (const value of values) {\n if (!value) {\n continue;\n }\n const size = name.length + value.length;\n if (used + size > remaining) {\n return { remaining: Math.max(0, remaining - used), truncated: true, values: taken };\n }\n used += size;\n taken.push(value);\n }\n\n return { remaining: Math.max(0, remaining - used), truncated: false, values: taken };\n}\n","import { headerTokenList } from './headers';\n\ntype HeaderValues = Record<string, string | string[]>;\n\nexport function isWebsocketUpgrade(\n statusCode: number,\n requestHeaders: HeaderValues | undefined,\n responseHeaders: HeaderValues | undefined,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasToken(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasToken(requestHeaders, 'upgrade', 'websocket');\n}\n\nexport function isWebsocketUpgradeFetch(\n statusCode: number,\n requestHeaders: Headers,\n responseHeaders: Headers,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasTokenFetch(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasTokenFetch(requestHeaders, 'upgrade', 'websocket');\n}\n\nfunction headerHasToken(headers: HeaderValues | undefined, name: string, token: string): boolean {\n if (!headers) {\n return false;\n }\n const values = headers[name] ?? headers[name.toLowerCase()] ?? headers[name.toUpperCase()];\n if (!values) {\n return false;\n }\n const tokens = headerTokenList(values);\n return tokens.some((value) => value.toLowerCase() === token.toLowerCase());\n}\n\nfunction headerHasTokenFetch(headers: Headers, name: string, token: string): boolean {\n const value = headers.get(name);\n if (!value) {\n return false;\n }\n return value.split(',').some((part) => part.trim().toLowerCase() === token.toLowerCase());\n}\n","const utf8Decoder =\n typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { fatal: true }) : null;\nconst utf8DecoderLenient = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8') : null;\nconst maybeBuffer = (\n globalThis as typeof globalThis & {\n Buffer?: { from(data: Uint8Array): { toString(encoding?: string): string } };\n }\n).Buffer;\n\nexport function encodeBase64(bytes: Uint8Array): string {\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('base64');\n }\n let binary = '';\n for (let i = 0; i < bytes.length; i += 1) {\n const byte = bytes[i];\n if (byte === undefined) {\n continue;\n }\n binary += String.fromCharCode(byte);\n }\n if (typeof btoa !== 'undefined') {\n return btoa(binary);\n }\n return '';\n}\n\nexport function isValidUtf8(bytes: Uint8Array): boolean {\n if (!utf8Decoder) {\n return false;\n }\n try {\n utf8Decoder.decode(bytes);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function decodeUtf8(bytes: Uint8Array): string {\n if (utf8DecoderLenient) {\n return utf8DecoderLenient.decode(bytes);\n }\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('utf8');\n }\n return '';\n}\n","import type { CapturedBody } from './types';\nimport { decodeUtf8, encodeBase64, isValidUtf8 } from './encoding';\n\n// eslint-disable-next-line no-control-regex\nconst controlChars = /[\\x00-\\x1F\\x7F]/g;\n\nexport function sanitizeLogString(value: string): string {\n if (!value) {\n return value;\n }\n return value.replace(controlChars, '');\n}\n\nexport function sanitizeHeaderValues(\n headers: Record<string, string | string[]> | undefined,\n): Record<string, string | string[]> | undefined {\n if (!headers) {\n return undefined;\n }\n\n const sanitized: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n const name = sanitizeLogString(key);\n if (Array.isArray(value)) {\n sanitized[name] = value.map((entry) => sanitizeLogString(entry));\n } else {\n sanitized[name] = sanitizeLogString(value);\n }\n }\n return sanitized;\n}\n\nexport function makeCapturedBody(\n bytes: Uint8Array | undefined,\n totalBytes: number,\n truncated: boolean,\n mode: 'text' | 'base64',\n): CapturedBody | undefined {\n if (!bytes) {\n return undefined;\n }\n\n if (mode === 'base64') {\n return {\n bytes: totalBytes,\n encoding: 'base64',\n truncated,\n value: encodeBase64(bytes),\n };\n }\n\n if (isValidUtf8(bytes)) {\n return {\n bytes: totalBytes,\n encoding: 'utf8',\n truncated,\n value: decodeUtf8(bytes),\n };\n }\n\n return {\n bytes: totalBytes,\n encoding: 'base64',\n truncated,\n value: encodeBase64(bytes),\n };\n}\n","import type { Logger, LogLevel } from './types';\n\nconst logLevelOrder: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nexport function logWithLevel(\n logger: Logger,\n level: LogLevel,\n threshold: LogLevel,\n message: string,\n fields?: Record<string, unknown>,\n): void {\n if (logLevelOrder[level] < logLevelOrder[threshold]) {\n return;\n }\n\n const fn =\n logger[level] ?? logger.warn ?? logger.info ?? logger.debug ?? logger.error ?? console.log;\n\n try {\n fn.call(logger, message, fields);\n } catch {\n // Logging should never disrupt instrumentation.\n }\n}\n","/**\n * Generates a UUIDv7 string.\n * Uses crypto.getRandomValues which is available in all modern JS runtimes\n * (browsers, Node.js 15+, Deno, Bun, Cloudflare Workers, Vercel Edge, etc.)\n */\nexport function uuidv7(): string {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n\n // Encode timestamp in first 48 bits\n const timestamp = BigInt(Date.now());\n bytes[0] = Number((timestamp >> 40n) & 0xffn);\n bytes[1] = Number((timestamp >> 32n) & 0xffn);\n bytes[2] = Number((timestamp >> 24n) & 0xffn);\n bytes[3] = Number((timestamp >> 16n) & 0xffn);\n bytes[4] = Number((timestamp >> 8n) & 0xffn);\n bytes[5] = Number(timestamp & 0xffn);\n\n // Set version (7) and variant (RFC 4122)\n const byte6 = bytes[6] ?? 0;\n const byte8 = bytes[8] ?? 0;\n bytes[6] = (byte6 & 0x0f) | 0x70;\n bytes[8] = (byte8 & 0x3f) | 0x80;\n\n // Format as UUID string\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0'));\n return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${hex.slice(10).join('')}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACkBA,IAAM,aAAa,oBAAI,QAAmC;AAC1D,IAAM,YAAY,oBAAI,QAA8B;AAM7C,SAAS,gBAAgB,KAA4C;AAC1E,SAAO,WAAW,IAAI,GAAG;AAC3B;AAEO,SAAS,WAAW,QAAgB,OAA2B;AACpE,YAAU,IAAI,QAAQ,KAAK;AAC7B;AAEO,SAAS,qBAAqB,QAA0C;AAC7E,QAAM,QAAQ,mBAAmB,MAAM;AACvC,SAAO,OAAO;AAChB;AAEO,SAAS,mBAAmB,QAA2C;AAC5E,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAO;AAAA,EACT;AACA,MAAI,UAAU,IAAI,MAAM,GAAG;AACzB,WAAO,UAAU,IAAI,MAAM;AAAA,EAC7B;AAEA,QAAM,WAAW,iBAAiB,MAAiC;AACnE,MAAI,YAAY,UAAU,IAAI,QAAQ,GAAG;AACvC,WAAO,UAAU,IAAI,QAAQ;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,KAA6C;AACrE,MAAI,IAAI,OAAO,OAAO,IAAI,QAAQ,UAAU;AAC1C,WAAO,IAAI;AAAA,EACb;AACA,MAAI,IAAI,OAAO,OAAO,IAAI,QAAQ,UAAU;AAC1C,UAAM,MAAM,IAAI;AAChB,QAAI,IAAI,OAAO,OAAO,IAAI,QAAQ,UAAU;AAC1C,aAAO,IAAI;AAAA,IACb;AACA,WAAO;AAAA,EACT;AACA,MAAI,IAAI,WAAW,OAAO,IAAI,YAAY,UAAU;AAClD,UAAM,UAAU,IAAI;AACpB,QAAI,QAAQ,OAAO,OAAO,QAAQ,QAAQ,UAAU;AAClD,aAAO,QAAQ;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ACxEO,IAAM,gBAAN,MAAoB;AAAA,EAOzB,YAAY,OAAe;AACzB,UAAM,aAAa,OAAO,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI;AACjE,UAAM,aAAa,KAAK,IAAI,YAAY,KAAK,IAAI;AACjD,SAAK,SAAS,IAAI,WAAW,UAAU;AACvC,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,gBAAgB;AACrB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,QAAoB;AAClB,WAAO,KAAK,OAAO,MAAM,GAAG,KAAK,MAAM;AAAA,EACzC;AAAA,EAEA,gBAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,aAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,OAAyB;AAC7B,QAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC;AAAA,IACF;AAEA,SAAK,SAAS,MAAM;AACpB,QAAI,KAAK,SAAS,GAAG;AACnB,WAAK,gBAAgB;AACrB;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,QAAQ,KAAK;AACpC,QAAI,aAAa,GAAG;AAClB,WAAK,gBAAgB;AACrB;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,IAAI,WAAW,MAAM,MAAM;AAC/C,SAAK,eAAe,KAAK,SAAS,MAAM;AACxC,SAAK,OAAO,IAAI,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,MAAM;AACtD,SAAK,UAAU;AACf,QAAI,SAAS,MAAM,QAAQ;AACzB,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,eAAe,MAAoB;AACzC,QAAI,KAAK,OAAO,UAAU,MAAM;AAC9B;AAAA,IACF;AAEA,QAAI,WAAW,KAAK,OAAO;AAC3B,QAAI,aAAa,GAAG;AAClB,iBAAW;AAAA,IACb;AACA,WAAO,WAAW,MAAM;AACtB,kBAAY;AAAA,IACd;AACA,QAAI,WAAW,KAAK,OAAO;AACzB,iBAAW,KAAK;AAAA,IAClB;AACA,UAAM,OAAO,IAAI,WAAW,QAAQ;AACpC,SAAK,IAAI,KAAK,OAAO,SAAS,GAAG,KAAK,MAAM,CAAC;AAC7C,SAAK,SAAS;AAAA,EAChB;AACF;;;ACzEO,SAAS,4BACd,SACmC;AACnC,QAAM,SAA4C,CAAC;AACnD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,SAAS,MAAM;AACjB;AAAA,IACF;AACA,UAAM,OAAO,IAAI,KAAK;AACtB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,UAAU,MAAM,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE;AAC7C,UAAI,QAAQ,SAAS,GAAG;AACtB,eAAO,IAAI,IAAI,QAAQ,WAAW,IAAI,QAAQ,CAAC,IAAK;AAAA,MACtD;AAAA,IACF,OAAO;AACL,aAAO,IAAI,IAAI,GAAG,KAAK;AAAA,IACzB;AAAA,EACF;AACA,SAAO,OAAO,KAAK,MAAM,EAAE,WAAW,IAAI,CAAC,IAAI;AACjD;AAEO,SAAS,6BAA6B,SAAqD;AAChG,SAAO,sCAAsC,SAAS,OAAO,iBAAiB,EAAE;AAClF;AAEO,SAAS,sCACd,SACA,UACe;AACf,QAAM,SAA4C,CAAC;AACnD,MAAI,YAAY;AAChB,MAAI,YAAY,OAAO,SAAS,QAAQ,IAAI,KAAK,IAAI,GAAG,QAAQ,IAAI,OAAO;AAC3E,QAAM,YAAY,aAAa,OAAO;AACtC,MAAI,WAAW;AACb,UAAM,SAAS,iBAAiB,cAAc,WAAW,SAAS;AAClE,gBAAY,OAAO;AACnB,QAAI,OAAO,WAAW;AACpB,kBAAY;AAAA,IACd;AACA,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,aAAO,YAAY,IAAI,OAAO,OAAO,WAAW,IAAI,OAAO,OAAO,CAAC,IAAK,OAAO;AAAA,IACjF;AAAA,EACF;AAEA,UAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC9B,UAAM,OAAO,IAAI,KAAK;AACtB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,QAAI,KAAK,YAAY,MAAM,gBAAgB,WAAW;AACpD;AAAA,IACF;AACA,UAAM,SAAS,iBAAiB,MAAM,CAAC,KAAK,GAAG,SAAS;AACxD,gBAAY,OAAO;AACnB,QAAI,OAAO,WAAW;AACpB,kBAAY;AAAA,IACd;AACA,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,aAAO,IAAI,IAAI,OAAO,OAAO,WAAW,IAAI,OAAO,OAAO,CAAC,IAAK,OAAO;AAAA,IACzE;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,SAAS,OAAO,KAAK,MAAM,EAAE,WAAW,IAAI,CAAC,IAAI;AAAA,IACjD;AAAA,EACF;AACF;AAEO,SAAS,gBAAgB,QAAiD;AAC/E,MAAI,CAAC,QAAQ;AACX,WAAO,CAAC;AAAA,EACV;AACA,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,WAAO,YAAY,MAAM;AAAA,EAC3B;AACA,SAAO,YAAY,CAAC,MAAM,CAAC;AAC7B;AAEA,SAAS,YAAY,QAA4B;AAC/C,QAAM,SAAmB,CAAC;AAC1B,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,eAAW,QAAQ,MAAM,MAAM,GAAG,GAAG;AACnC,YAAM,UAAU,KAAK,KAAK;AAC1B,UAAI,SAAS;AACX,eAAO,KAAK,OAAO;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aAAa,SAAmC;AACvD,QAAM,QAAQ;AACd,MAAI,OAAO,MAAM,iBAAiB,YAAY;AAC5C,UAAM,SAAS,MAAM,aAAa;AAClC,WAAO,OAAO,SAAS,IAAI,SAAS;AAAA,EACtC;AACA,SAAO;AACT;AAEA,SAAS,iBACP,MACA,QACA,WAC6D;AAC7D,MAAI,aAAa,GAAG;AAClB,WAAO,EAAE,WAAW,GAAG,WAAW,MAAM,QAAQ,CAAC,EAAE;AAAA,EACrD;AAEA,QAAM,QAAkB,CAAC;AACzB,MAAI,OAAO;AACX,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,UAAM,OAAO,KAAK,SAAS,MAAM;AACjC,QAAI,OAAO,OAAO,WAAW;AAC3B,aAAO,EAAE,WAAW,KAAK,IAAI,GAAG,YAAY,IAAI,GAAG,WAAW,MAAM,QAAQ,MAAM;AAAA,IACpF;AACA,YAAQ;AACR,UAAM,KAAK,KAAK;AAAA,EAClB;AAEA,SAAO,EAAE,WAAW,KAAK,IAAI,GAAG,YAAY,IAAI,GAAG,WAAW,OAAO,QAAQ,MAAM;AACrF;;;ACnIO,SAAS,mBACd,YACA,gBACA,iBACS;AACT,MAAI,eAAe,KAAK;AACtB,WAAO;AAAA,EACT;AAEA,MAAI,eAAe,iBAAiB,WAAW,WAAW,GAAG;AAC3D,WAAO;AAAA,EACT;AACA,SAAO,eAAe,gBAAgB,WAAW,WAAW;AAC9D;AAEO,SAAS,wBACd,YACA,gBACA,iBACS;AACT,MAAI,eAAe,KAAK;AACtB,WAAO;AAAA,EACT;AAEA,MAAI,oBAAoB,iBAAiB,WAAW,WAAW,GAAG;AAChE,WAAO;AAAA,EACT;AACA,SAAO,oBAAoB,gBAAgB,WAAW,WAAW;AACnE;AAEA,SAAS,eAAe,SAAmC,MAAc,OAAwB;AAC/F,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,QAAM,SAAS,QAAQ,IAAI,KAAK,QAAQ,KAAK,YAAY,CAAC,KAAK,QAAQ,KAAK,YAAY,CAAC;AACzF,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,QAAM,SAAS,gBAAgB,MAAM;AACrC,SAAO,OAAO,KAAK,CAAC,UAAU,MAAM,YAAY,MAAM,MAAM,YAAY,CAAC;AAC3E;AAEA,SAAS,oBAAoB,SAAkB,MAAc,OAAwB;AACnF,QAAM,QAAQ,QAAQ,IAAI,IAAI;AAC9B,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,SAAO,MAAM,MAAM,GAAG,EAAE,KAAK,CAAC,SAAS,KAAK,KAAK,EAAE,YAAY,MAAM,MAAM,YAAY,CAAC;AAC1F;;;ACpDA,IAAM,cACJ,OAAO,gBAAgB,cAAc,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,IAAI;AACnF,IAAM,qBAAqB,OAAO,gBAAgB,cAAc,IAAI,YAAY,OAAO,IAAI;AAC3F,IAAM,cACJ,WAGA;AAEK,SAAS,aAAa,OAA2B;AACtD,MAAI,aAAa;AACf,WAAO,YAAY,KAAK,KAAK,EAAE,SAAS,QAAQ;AAAA,EAClD;AACA,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,SAAS,QAAW;AACtB;AAAA,IACF;AACA,cAAU,OAAO,aAAa,IAAI;AAAA,EACpC;AACA,MAAI,OAAO,SAAS,aAAa;AAC/B,WAAO,KAAK,MAAM;AAAA,EACpB;AACA,SAAO;AACT;AAEO,SAAS,YAAY,OAA4B;AACtD,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AACA,MAAI;AACF,gBAAY,OAAO,KAAK;AACxB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,OAA2B;AACpD,MAAI,oBAAoB;AACtB,WAAO,mBAAmB,OAAO,KAAK;AAAA,EACxC;AACA,MAAI,aAAa;AACf,WAAO,YAAY,KAAK,KAAK,EAAE,SAAS,MAAM;AAAA,EAChD;AACA,SAAO;AACT;;;ACfO,SAAS,iBACd,OACA,YACA,WACA,MAC0B;AAC1B,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,UAAU;AACrB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV;AAAA,MACA,OAAO,aAAa,KAAK;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,YAAY,KAAK,GAAG;AACtB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV;AAAA,MACA,OAAO,WAAW,KAAK;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,UAAU;AAAA,IACV;AAAA,IACA,OAAO,aAAa,KAAK;AAAA,EAC3B;AACF;;;AChEA,IAAM,gBAA0C;AAAA,EAC9C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAEO,SAAS,aACd,QACA,OACA,WACA,SACA,QACM;AACN,MAAI,cAAc,KAAK,IAAI,cAAc,SAAS,GAAG;AACnD;AAAA,EACF;AAEA,QAAM,KACJ,OAAO,KAAK,KAAK,OAAO,QAAQ,OAAO,QAAQ,OAAO,SAAS,OAAO,SAAS,QAAQ;AAEzF,MAAI;AACF,OAAG,KAAK,QAAQ,SAAS,MAAM;AAAA,EACjC,QAAQ;AAAA,EAER;AACF;;;ACvBO,SAAS,SAAiB;AAC/B,QAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,SAAO,gBAAgB,KAAK;AAG5B,QAAM,YAAY,OAAO,KAAK,IAAI,CAAC;AACnC,QAAM,CAAC,IAAI,OAAQ,aAAa,MAAO,KAAK;AAC5C,QAAM,CAAC,IAAI,OAAQ,aAAa,MAAO,KAAK;AAC5C,QAAM,CAAC,IAAI,OAAQ,aAAa,MAAO,KAAK;AAC5C,QAAM,CAAC,IAAI,OAAQ,aAAa,MAAO,KAAK;AAC5C,QAAM,CAAC,IAAI,OAAQ,aAAa,KAAM,KAAK;AAC3C,QAAM,CAAC,IAAI,OAAO,YAAY,KAAK;AAGnC,QAAM,QAAQ,MAAM,CAAC,KAAK;AAC1B,QAAM,QAAQ,MAAM,CAAC,KAAK;AAC1B,QAAM,CAAC,IAAK,QAAQ,KAAQ;AAC5B,QAAM,CAAC,IAAK,QAAQ,KAAQ;AAG5B,QAAM,MAAM,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AACpE,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC;AACnJ;;;ARXO,SAAS,oBAAoB,QAAgB,KAAwB;AAC1E,QAAM,QAAQ,gBAAgB,GAAG;AACjC,MAAI,CAAC,OAAO;AACV;AAAA,EACF;AACA,aAAW,QAAQ,KAAK;AAC1B;AAEO,SAAS,yBAAyB,QAA0C;AACjF,SAAO,qBAAqB,MAAM;AACpC;AAEO,SAAS,gBAAgB,KAAkB,OAAqB;AACrE,QAAM,QAAQ,gBAAgB,GAAG;AACjC,MAAI,CAAC,OAAO;AACV;AAAA,EACF;AACA,QAAM,aACJ,MAAM,OAAO,MAAM,aAAa,MAAM,OAAO,MAAM,aAC/C,MAAM,OAAO,MAAM,WAAW,KAAK,IACnC;AACN,QAAM,QAAQ,QAAQ;AACxB;AAEO,SAAS,oBAAoB,KAAkB,WAAyB;AAC7E,QAAM,QAAQ,gBAAgB,GAAG;AACjC,MAAI,CAAC,OAAO;AACV;AAAA,EACF;AACA,QAAM,QAAQ,YAAY;AAC1B,QAAM,QAAQ,YAAY;AAC5B;AAEO,SAAS,mBACd,KACA,SACM;AACN,QAAM,QAAQ,gBAAgB,GAAG;AACjC,MAAI,CAAC,SAAS,CAAC,SAAS;AACtB;AAAA,EACF;AACA,QAAM,kBAAkB;AAC1B;AAEO,SAAS,qBACd,KACA,WACM;AACN,QAAM,QAAQ,gBAAgB,GAAG;AACjC,MAAI,CAAC,SAAS,CAAC,WAAW;AACxB;AAAA,EACF;AACA,QAAM,oBAAoB;AAC5B;","names":[]}
@@ -1,4 +1,4 @@
1
- import { C as CapturedBody, b as Logger, L as LogLevel, d as XrayContext, e as CaptureConfig, f as RedactionConfig } from './types-CB9CGfc5.cjs';
1
+ import { C as CapturedBody, b as Logger, L as LogLevel, d as XrayContext, e as CaptureConfig, f as RedactionConfig } from './types-Z1nirh-F.cjs';
2
2
  import '@opentelemetry/sdk-trace-base';
3
3
 
4
4
  declare function makeCapturedBody(bytes: Uint8Array | undefined, totalBytes: number, truncated: boolean, mode: 'text' | 'base64'): CapturedBody | undefined;
@@ -33,6 +33,13 @@ declare function isWebsocketUpgradeFetch(statusCode: number, requestHeaders: Hea
33
33
 
34
34
  declare function logWithLevel(logger: Logger, level: LogLevel, threshold: LogLevel, message: string, fields?: Record<string, unknown>): void;
35
35
 
36
+ /**
37
+ * Generates a UUIDv7 string.
38
+ * Uses crypto.getRandomValues which is available in all modern JS runtimes
39
+ * (browsers, Node.js 15+, Deno, Bun, Cloudflare Workers, Vercel Edge, etc.)
40
+ */
41
+ declare function uuidv7(): string;
42
+
36
43
  declare function bindContextToObject(target: object, ctx: XrayContext): void;
37
44
  declare function getXrayContextFromObject(target: unknown): XrayContext | undefined;
38
45
  declare function setContextRoute(ctx: XrayContext, route: string): void;
@@ -40,4 +47,4 @@ declare function setContextRequestId(ctx: XrayContext, requestId: string): void;
40
47
  declare function setCaptureOverride(ctx: XrayContext, capture: Partial<CaptureConfig> | undefined): void;
41
48
  declare function setRedactionOverride(ctx: XrayContext, redaction: Partial<RedactionConfig> | undefined): void;
42
49
 
43
- export { LimitedBuffer, bindContextToObject, getXrayContextFromObject, headerTokenList, headerValuesFromFetchHeaders, headerValuesFromFetchHeadersWithLimit, headerValuesFromNodeHeaders, isWebsocketUpgrade, isWebsocketUpgradeFetch, logWithLevel, makeCapturedBody, setCaptureOverride, setContextRequestId, setContextRoute, setRedactionOverride };
50
+ export { LimitedBuffer, bindContextToObject, getXrayContextFromObject, headerTokenList, headerValuesFromFetchHeaders, headerValuesFromFetchHeadersWithLimit, headerValuesFromNodeHeaders, isWebsocketUpgrade, isWebsocketUpgradeFetch, logWithLevel, makeCapturedBody, setCaptureOverride, setContextRequestId, setContextRoute, setRedactionOverride, uuidv7 };
@@ -1,4 +1,4 @@
1
- import { C as CapturedBody, b as Logger, L as LogLevel, d as XrayContext, e as CaptureConfig, f as RedactionConfig } from './types-CB9CGfc5.js';
1
+ import { C as CapturedBody, b as Logger, L as LogLevel, d as XrayContext, e as CaptureConfig, f as RedactionConfig } from './types-Z1nirh-F.js';
2
2
  import '@opentelemetry/sdk-trace-base';
3
3
 
4
4
  declare function makeCapturedBody(bytes: Uint8Array | undefined, totalBytes: number, truncated: boolean, mode: 'text' | 'base64'): CapturedBody | undefined;
@@ -33,6 +33,13 @@ declare function isWebsocketUpgradeFetch(statusCode: number, requestHeaders: Hea
33
33
 
34
34
  declare function logWithLevel(logger: Logger, level: LogLevel, threshold: LogLevel, message: string, fields?: Record<string, unknown>): void;
35
35
 
36
+ /**
37
+ * Generates a UUIDv7 string.
38
+ * Uses crypto.getRandomValues which is available in all modern JS runtimes
39
+ * (browsers, Node.js 15+, Deno, Bun, Cloudflare Workers, Vercel Edge, etc.)
40
+ */
41
+ declare function uuidv7(): string;
42
+
36
43
  declare function bindContextToObject(target: object, ctx: XrayContext): void;
37
44
  declare function getXrayContextFromObject(target: unknown): XrayContext | undefined;
38
45
  declare function setContextRoute(ctx: XrayContext, route: string): void;
@@ -40,4 +47,4 @@ declare function setContextRequestId(ctx: XrayContext, requestId: string): void;
40
47
  declare function setCaptureOverride(ctx: XrayContext, capture: Partial<CaptureConfig> | undefined): void;
41
48
  declare function setRedactionOverride(ctx: XrayContext, redaction: Partial<RedactionConfig> | undefined): void;
42
49
 
43
- export { LimitedBuffer, bindContextToObject, getXrayContextFromObject, headerTokenList, headerValuesFromFetchHeaders, headerValuesFromFetchHeadersWithLimit, headerValuesFromNodeHeaders, isWebsocketUpgrade, isWebsocketUpgradeFetch, logWithLevel, makeCapturedBody, setCaptureOverride, setContextRequestId, setContextRoute, setRedactionOverride };
50
+ export { LimitedBuffer, bindContextToObject, getXrayContextFromObject, headerTokenList, headerValuesFromFetchHeaders, headerValuesFromFetchHeadersWithLimit, headerValuesFromNodeHeaders, isWebsocketUpgrade, isWebsocketUpgradeFetch, logWithLevel, makeCapturedBody, setCaptureOverride, setContextRequestId, setContextRoute, setRedactionOverride, uuidv7 };
package/dist/internal.js CHANGED
@@ -3,8 +3,9 @@ import {
3
3
  getContextFromObject,
4
4
  getContextState,
5
5
  logWithLevel,
6
- makeCapturedBody
7
- } from "./chunk-XI5E6C7G.js";
6
+ makeCapturedBody,
7
+ uuidv7
8
+ } from "./chunk-HGFCHC7O.js";
8
9
 
9
10
  // src/limited_buffer.ts
10
11
  var LimitedBuffer = class {
@@ -279,6 +280,7 @@ export {
279
280
  setCaptureOverride,
280
281
  setContextRequestId,
281
282
  setContextRoute,
282
- setRedactionOverride
283
+ setRedactionOverride,
284
+ uuidv7
283
285
  };
284
286
  //# sourceMappingURL=internal.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/limited_buffer.ts","../src/headers.ts","../src/websocket.ts","../src/internal.ts"],"sourcesContent":["export class LimitedBuffer {\n private buffer: Uint8Array;\n private length: number;\n private readonly limit: number;\n private truncatedFlag: boolean;\n private total: number;\n\n constructor(limit: number) {\n const normalized = Number.isFinite(limit) ? Math.max(0, limit) : 0;\n const initialCap = Math.min(normalized, 32 * 1024);\n this.buffer = new Uint8Array(initialCap);\n this.length = 0;\n this.limit = normalized;\n this.truncatedFlag = false;\n this.total = 0;\n }\n\n bytes(): Uint8Array {\n return this.buffer.slice(0, this.length);\n }\n\n capturedBytes(): number {\n return this.length;\n }\n\n totalBytes(): number {\n return this.total;\n }\n\n truncated(): boolean {\n return this.truncatedFlag;\n }\n\n write(chunk: Uint8Array): void {\n if (!chunk || chunk.length === 0) {\n return;\n }\n\n this.total += chunk.length;\n if (this.limit <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const remaining = this.limit - this.length;\n if (remaining <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const toCopy = Math.min(remaining, chunk.length);\n this.ensureCapacity(this.length + toCopy);\n this.buffer.set(chunk.subarray(0, toCopy), this.length);\n this.length += toCopy;\n if (toCopy < chunk.length) {\n this.truncatedFlag = true;\n }\n }\n\n private ensureCapacity(size: number): void {\n if (this.buffer.length >= size) {\n return;\n }\n\n let nextSize = this.buffer.length;\n if (nextSize === 0) {\n nextSize = 1;\n }\n while (nextSize < size) {\n nextSize *= 2;\n }\n if (nextSize > this.limit) {\n nextSize = this.limit;\n }\n const next = new Uint8Array(nextSize);\n next.set(this.buffer.subarray(0, this.length));\n this.buffer = next;\n }\n}\n","export type HeaderCapture = {\n headers: Record<string, string | string[]>;\n truncated: boolean;\n};\n\nexport function headerValuesFromNodeHeaders(\n headers: Record<string, string | string[] | number | undefined>,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value == null) {\n continue;\n }\n const name = key.trim();\n if (!name) {\n continue;\n }\n if (Array.isArray(value)) {\n const entries = value.map((item) => `${item}`);\n if (entries.length > 0) {\n result[name] = entries.length === 1 ? entries[0]! : entries;\n }\n } else {\n result[name] = `${value}`;\n }\n }\n return Object.keys(result).length === 0 ? {} : result;\n}\n\nexport function headerValuesFromFetchHeaders(headers: Headers): Record<string, string | string[]> {\n return headerValuesFromFetchHeadersWithLimit(headers, Number.POSITIVE_INFINITY).headers;\n}\n\nexport function headerValuesFromFetchHeadersWithLimit(\n headers: Headers,\n maxBytes: number,\n): HeaderCapture {\n const result: Record<string, string | string[]> = {};\n let truncated = false;\n let remaining = Number.isFinite(maxBytes) ? Math.max(0, maxBytes) : Number.POSITIVE_INFINITY;\n const setCookie = getSetCookie(headers);\n if (setCookie) {\n const values = takeHeaderValues('set-cookie', setCookie, remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result['set-cookie'] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n }\n\n headers.forEach((value, key) => {\n const name = key.trim();\n if (!name) {\n return;\n }\n if (name.toLowerCase() === 'set-cookie' && setCookie) {\n return;\n }\n const values = takeHeaderValues(name, [value], remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result[name] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n });\n\n return {\n headers: Object.keys(result).length === 0 ? {} : result,\n truncated,\n };\n}\n\nexport function headerTokenList(values: string[] | string | undefined): string[] {\n if (!values) {\n return [];\n }\n if (Array.isArray(values)) {\n return splitTokens(values);\n }\n return splitTokens([values]);\n}\n\nfunction splitTokens(values: string[]): string[] {\n const tokens: string[] = [];\n for (const value of values) {\n if (!value) {\n continue;\n }\n for (const part of value.split(',')) {\n const trimmed = part.trim();\n if (trimmed) {\n tokens.push(trimmed);\n }\n }\n }\n return tokens;\n}\n\nfunction getSetCookie(headers: Headers): string[] | null {\n const maybe = headers as Headers & { getSetCookie?: () => string[] };\n if (typeof maybe.getSetCookie === 'function') {\n const values = maybe.getSetCookie();\n return values.length > 0 ? values : null;\n }\n return null;\n}\n\nfunction takeHeaderValues(\n name: string,\n values: string[],\n remaining: number,\n): { values: string[]; remaining: number; truncated: boolean } {\n if (remaining <= 0) {\n return { remaining: 0, truncated: true, values: [] };\n }\n\n const taken: string[] = [];\n let used = 0;\n for (const value of values) {\n if (!value) {\n continue;\n }\n const size = name.length + value.length;\n if (used + size > remaining) {\n return { remaining: Math.max(0, remaining - used), truncated: true, values: taken };\n }\n used += size;\n taken.push(value);\n }\n\n return { remaining: Math.max(0, remaining - used), truncated: false, values: taken };\n}\n","import { headerTokenList } from './headers';\n\ntype HeaderValues = Record<string, string | string[]>;\n\nexport function isWebsocketUpgrade(\n statusCode: number,\n requestHeaders: HeaderValues | undefined,\n responseHeaders: HeaderValues | undefined,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasToken(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasToken(requestHeaders, 'upgrade', 'websocket');\n}\n\nexport function isWebsocketUpgradeFetch(\n statusCode: number,\n requestHeaders: Headers,\n responseHeaders: Headers,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasTokenFetch(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasTokenFetch(requestHeaders, 'upgrade', 'websocket');\n}\n\nfunction headerHasToken(headers: HeaderValues | undefined, name: string, token: string): boolean {\n if (!headers) {\n return false;\n }\n const values = headers[name] ?? headers[name.toLowerCase()] ?? headers[name.toUpperCase()];\n if (!values) {\n return false;\n }\n const tokens = headerTokenList(values);\n return tokens.some((value) => value.toLowerCase() === token.toLowerCase());\n}\n\nfunction headerHasTokenFetch(headers: Headers, name: string, token: string): boolean {\n const value = headers.get(name);\n if (!value) {\n return false;\n }\n return value.split(',').some((part) => part.trim().toLowerCase() === token.toLowerCase());\n}\n","import type { CaptureConfig, RedactionConfig } from './config';\nimport type { XrayContext } from './types';\nimport { bindObject, getContextFromObject, getContextState } from './state';\n\nexport { LimitedBuffer } from './limited_buffer';\nexport {\n headerValuesFromFetchHeaders,\n headerValuesFromFetchHeadersWithLimit,\n headerValuesFromNodeHeaders,\n headerTokenList,\n} from './headers';\nexport { isWebsocketUpgrade, isWebsocketUpgradeFetch } from './websocket';\nexport { makeCapturedBody } from './request_log';\nexport { logWithLevel } from './logger';\n\nexport function bindContextToObject(target: object, ctx: XrayContext): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n bindObject(target, state);\n}\n\nexport function getXrayContextFromObject(target: unknown): XrayContext | undefined {\n return getContextFromObject(target);\n}\n\nexport function setContextRoute(ctx: XrayContext, route: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n const normalized =\n state.config.route.normalize && state.config.route.normalizer\n ? state.config.route.normalizer(route)\n : route;\n state.request.route = normalized;\n}\n\nexport function setContextRequestId(ctx: XrayContext, requestId: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n state.request.requestId = requestId;\n state.context.requestId = requestId;\n}\n\nexport function setCaptureOverride(\n ctx: XrayContext,\n capture: Partial<CaptureConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !capture) {\n return;\n }\n state.captureOverride = capture;\n}\n\nexport function setRedactionOverride(\n ctx: XrayContext,\n redaction: Partial<RedactionConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !redaction) {\n return;\n }\n state.redactionOverride = redaction;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/limited_buffer.ts","../src/headers.ts","../src/websocket.ts","../src/internal.ts"],"sourcesContent":["export class LimitedBuffer {\n private buffer: Uint8Array;\n private length: number;\n private readonly limit: number;\n private truncatedFlag: boolean;\n private total: number;\n\n constructor(limit: number) {\n const normalized = Number.isFinite(limit) ? Math.max(0, limit) : 0;\n const initialCap = Math.min(normalized, 32 * 1024);\n this.buffer = new Uint8Array(initialCap);\n this.length = 0;\n this.limit = normalized;\n this.truncatedFlag = false;\n this.total = 0;\n }\n\n bytes(): Uint8Array {\n return this.buffer.slice(0, this.length);\n }\n\n capturedBytes(): number {\n return this.length;\n }\n\n totalBytes(): number {\n return this.total;\n }\n\n truncated(): boolean {\n return this.truncatedFlag;\n }\n\n write(chunk: Uint8Array): void {\n if (!chunk || chunk.length === 0) {\n return;\n }\n\n this.total += chunk.length;\n if (this.limit <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const remaining = this.limit - this.length;\n if (remaining <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const toCopy = Math.min(remaining, chunk.length);\n this.ensureCapacity(this.length + toCopy);\n this.buffer.set(chunk.subarray(0, toCopy), this.length);\n this.length += toCopy;\n if (toCopy < chunk.length) {\n this.truncatedFlag = true;\n }\n }\n\n private ensureCapacity(size: number): void {\n if (this.buffer.length >= size) {\n return;\n }\n\n let nextSize = this.buffer.length;\n if (nextSize === 0) {\n nextSize = 1;\n }\n while (nextSize < size) {\n nextSize *= 2;\n }\n if (nextSize > this.limit) {\n nextSize = this.limit;\n }\n const next = new Uint8Array(nextSize);\n next.set(this.buffer.subarray(0, this.length));\n this.buffer = next;\n }\n}\n","export type HeaderCapture = {\n headers: Record<string, string | string[]>;\n truncated: boolean;\n};\n\nexport function headerValuesFromNodeHeaders(\n headers: Record<string, string | string[] | number | undefined>,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value == null) {\n continue;\n }\n const name = key.trim();\n if (!name) {\n continue;\n }\n if (Array.isArray(value)) {\n const entries = value.map((item) => `${item}`);\n if (entries.length > 0) {\n result[name] = entries.length === 1 ? entries[0]! : entries;\n }\n } else {\n result[name] = `${value}`;\n }\n }\n return Object.keys(result).length === 0 ? {} : result;\n}\n\nexport function headerValuesFromFetchHeaders(headers: Headers): Record<string, string | string[]> {\n return headerValuesFromFetchHeadersWithLimit(headers, Number.POSITIVE_INFINITY).headers;\n}\n\nexport function headerValuesFromFetchHeadersWithLimit(\n headers: Headers,\n maxBytes: number,\n): HeaderCapture {\n const result: Record<string, string | string[]> = {};\n let truncated = false;\n let remaining = Number.isFinite(maxBytes) ? Math.max(0, maxBytes) : Number.POSITIVE_INFINITY;\n const setCookie = getSetCookie(headers);\n if (setCookie) {\n const values = takeHeaderValues('set-cookie', setCookie, remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result['set-cookie'] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n }\n\n headers.forEach((value, key) => {\n const name = key.trim();\n if (!name) {\n return;\n }\n if (name.toLowerCase() === 'set-cookie' && setCookie) {\n return;\n }\n const values = takeHeaderValues(name, [value], remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result[name] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n });\n\n return {\n headers: Object.keys(result).length === 0 ? {} : result,\n truncated,\n };\n}\n\nexport function headerTokenList(values: string[] | string | undefined): string[] {\n if (!values) {\n return [];\n }\n if (Array.isArray(values)) {\n return splitTokens(values);\n }\n return splitTokens([values]);\n}\n\nfunction splitTokens(values: string[]): string[] {\n const tokens: string[] = [];\n for (const value of values) {\n if (!value) {\n continue;\n }\n for (const part of value.split(',')) {\n const trimmed = part.trim();\n if (trimmed) {\n tokens.push(trimmed);\n }\n }\n }\n return tokens;\n}\n\nfunction getSetCookie(headers: Headers): string[] | null {\n const maybe = headers as Headers & { getSetCookie?: () => string[] };\n if (typeof maybe.getSetCookie === 'function') {\n const values = maybe.getSetCookie();\n return values.length > 0 ? values : null;\n }\n return null;\n}\n\nfunction takeHeaderValues(\n name: string,\n values: string[],\n remaining: number,\n): { values: string[]; remaining: number; truncated: boolean } {\n if (remaining <= 0) {\n return { remaining: 0, truncated: true, values: [] };\n }\n\n const taken: string[] = [];\n let used = 0;\n for (const value of values) {\n if (!value) {\n continue;\n }\n const size = name.length + value.length;\n if (used + size > remaining) {\n return { remaining: Math.max(0, remaining - used), truncated: true, values: taken };\n }\n used += size;\n taken.push(value);\n }\n\n return { remaining: Math.max(0, remaining - used), truncated: false, values: taken };\n}\n","import { headerTokenList } from './headers';\n\ntype HeaderValues = Record<string, string | string[]>;\n\nexport function isWebsocketUpgrade(\n statusCode: number,\n requestHeaders: HeaderValues | undefined,\n responseHeaders: HeaderValues | undefined,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasToken(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasToken(requestHeaders, 'upgrade', 'websocket');\n}\n\nexport function isWebsocketUpgradeFetch(\n statusCode: number,\n requestHeaders: Headers,\n responseHeaders: Headers,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasTokenFetch(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasTokenFetch(requestHeaders, 'upgrade', 'websocket');\n}\n\nfunction headerHasToken(headers: HeaderValues | undefined, name: string, token: string): boolean {\n if (!headers) {\n return false;\n }\n const values = headers[name] ?? headers[name.toLowerCase()] ?? headers[name.toUpperCase()];\n if (!values) {\n return false;\n }\n const tokens = headerTokenList(values);\n return tokens.some((value) => value.toLowerCase() === token.toLowerCase());\n}\n\nfunction headerHasTokenFetch(headers: Headers, name: string, token: string): boolean {\n const value = headers.get(name);\n if (!value) {\n return false;\n }\n return value.split(',').some((part) => part.trim().toLowerCase() === token.toLowerCase());\n}\n","import type { CaptureConfig, RedactionConfig } from './config';\nimport type { XrayContext } from './types';\nimport { bindObject, getContextFromObject, getContextState } from './state';\n\nexport { LimitedBuffer } from './limited_buffer';\nexport {\n headerValuesFromFetchHeaders,\n headerValuesFromFetchHeadersWithLimit,\n headerValuesFromNodeHeaders,\n headerTokenList,\n} from './headers';\nexport { isWebsocketUpgrade, isWebsocketUpgradeFetch } from './websocket';\nexport { makeCapturedBody } from './request_log';\nexport { logWithLevel } from './logger';\nexport { uuidv7 } from './uuid';\n\nexport function bindContextToObject(target: object, ctx: XrayContext): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n bindObject(target, state);\n}\n\nexport function getXrayContextFromObject(target: unknown): XrayContext | undefined {\n return getContextFromObject(target);\n}\n\nexport function setContextRoute(ctx: XrayContext, route: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n const normalized =\n state.config.route.normalize && state.config.route.normalizer\n ? state.config.route.normalizer(route)\n : route;\n state.request.route = normalized;\n}\n\nexport function setContextRequestId(ctx: XrayContext, requestId: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n state.request.requestId = requestId;\n state.context.requestId = requestId;\n}\n\nexport function setCaptureOverride(\n ctx: XrayContext,\n capture: Partial<CaptureConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !capture) {\n return;\n }\n state.captureOverride = capture;\n}\n\nexport function setRedactionOverride(\n ctx: XrayContext,\n redaction: Partial<RedactionConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !redaction) {\n return;\n }\n state.redactionOverride = redaction;\n}\n"],"mappings":"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","names":[]}
@@ -21,17 +21,10 @@ interface RedactionConfig {
21
21
  }
22
22
  interface RequestIdConfig {
23
23
  /**
24
- * Incoming request header name to read request IDs from. Set or overwrite
25
- * this header in your own middleware before X-ray runs if you don't want to
26
- * trust client-supplied IDs. This is normalized to lowercase during
27
- * configuration.
24
+ * Response header name to read request IDs from. This is normalized to
25
+ * lowercase during configuration.
28
26
  */
29
27
  header: string;
30
- /**
31
- * Generate a UUIDv7 when no request ID is present on the request or header.
32
- * When disabled and no ID is found, X-ray uses an empty string.
33
- */
34
- generate: boolean;
35
28
  }
36
29
  interface RouteConfig {
37
30
  normalize: boolean;
@@ -48,9 +41,8 @@ interface XrayConfig {
48
41
  capture?: Partial<CaptureConfig>;
49
42
  redaction?: Partial<RedactionConfig>;
50
43
  /**
51
- * Request ID resolution settings. The header is read from incoming request headers.
52
- * Set or overwrite that header before X-ray runs if you don't want to trust
53
- * client-supplied IDs.
44
+ * Request ID resolution settings. The header is read from response headers at
45
+ * the end of the request.
54
46
  */
55
47
  requestId?: Partial<RequestIdConfig>;
56
48
  route?: Partial<RouteConfig>;
@@ -133,10 +125,8 @@ interface NormalizedRequest {
133
125
  headers: Record<string, string | string[]>;
134
126
  body?: CapturedBody;
135
127
  /**
136
- * Optional explicit request ID. If omitted, X-ray reads from incoming request
137
- * headers (and generates a UUIDv7 if enabled). When generation is disabled
138
- * and no ID is found, X-ray uses an empty string. Set or overwrite that
139
- * header before X-ray runs if you don't want to trust client-supplied IDs.
128
+ * Optional explicit request ID. If omitted, X-ray reads from response headers
129
+ * when the span is closed (and generates a UUIDv7 if none is present).
140
130
  */
141
131
  requestId?: string;
142
132
  remoteAddress?: string;
@@ -21,17 +21,10 @@ interface RedactionConfig {
21
21
  }
22
22
  interface RequestIdConfig {
23
23
  /**
24
- * Incoming request header name to read request IDs from. Set or overwrite
25
- * this header in your own middleware before X-ray runs if you don't want to
26
- * trust client-supplied IDs. This is normalized to lowercase during
27
- * configuration.
24
+ * Response header name to read request IDs from. This is normalized to
25
+ * lowercase during configuration.
28
26
  */
29
27
  header: string;
30
- /**
31
- * Generate a UUIDv7 when no request ID is present on the request or header.
32
- * When disabled and no ID is found, X-ray uses an empty string.
33
- */
34
- generate: boolean;
35
28
  }
36
29
  interface RouteConfig {
37
30
  normalize: boolean;
@@ -48,9 +41,8 @@ interface XrayConfig {
48
41
  capture?: Partial<CaptureConfig>;
49
42
  redaction?: Partial<RedactionConfig>;
50
43
  /**
51
- * Request ID resolution settings. The header is read from incoming request headers.
52
- * Set or overwrite that header before X-ray runs if you don't want to trust
53
- * client-supplied IDs.
44
+ * Request ID resolution settings. The header is read from response headers at
45
+ * the end of the request.
54
46
  */
55
47
  requestId?: Partial<RequestIdConfig>;
56
48
  route?: Partial<RouteConfig>;
@@ -133,10 +125,8 @@ interface NormalizedRequest {
133
125
  headers: Record<string, string | string[]>;
134
126
  body?: CapturedBody;
135
127
  /**
136
- * Optional explicit request ID. If omitted, X-ray reads from incoming request
137
- * headers (and generates a UUIDv7 if enabled). When generation is disabled
138
- * and no ID is found, X-ray uses an empty string. Set or overwrite that
139
- * header before X-ray runs if you don't want to trust client-supplied IDs.
128
+ * Optional explicit request ID. If omitted, X-ray reads from response headers
129
+ * when the span is closed (and generates a UUIDv7 if none is present).
140
130
  */
141
131
  requestId?: string;
142
132
  remoteAddress?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stainlessdev/xray-core",
3
- "version": "0.5.1-dev.6191ec4",
3
+ "version": "0.6.0-branch.bg-fix-req-id-gen.e29953f",
4
4
  "description": "Core instrumentation for Stainless X-ray request logging",
5
5
  "files": [
6
6
  "dist"
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/logger.ts","../src/encoding.ts","../src/request_log.ts","../src/state.ts"],"sourcesContent":["import type { Logger, LogLevel } from './types';\n\nconst logLevelOrder: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nexport function logWithLevel(\n logger: Logger,\n level: LogLevel,\n threshold: LogLevel,\n message: string,\n fields?: Record<string, unknown>,\n): void {\n if (logLevelOrder[level] < logLevelOrder[threshold]) {\n return;\n }\n\n const fn =\n logger[level] ?? logger.warn ?? logger.info ?? logger.debug ?? logger.error ?? console.log;\n\n try {\n fn.call(logger, message, fields);\n } catch {\n // Logging should never disrupt instrumentation.\n }\n}\n","const utf8Decoder =\n typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { fatal: true }) : null;\nconst utf8DecoderLenient = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8') : null;\nconst maybeBuffer = (\n globalThis as typeof globalThis & {\n Buffer?: { from(data: Uint8Array): { toString(encoding?: string): string } };\n }\n).Buffer;\n\nexport function encodeBase64(bytes: Uint8Array): string {\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('base64');\n }\n let binary = '';\n for (let i = 0; i < bytes.length; i += 1) {\n const byte = bytes[i];\n if (byte === undefined) {\n continue;\n }\n binary += String.fromCharCode(byte);\n }\n if (typeof btoa !== 'undefined') {\n return btoa(binary);\n }\n return '';\n}\n\nexport function isValidUtf8(bytes: Uint8Array): boolean {\n if (!utf8Decoder) {\n return false;\n }\n try {\n utf8Decoder.decode(bytes);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function decodeUtf8(bytes: Uint8Array): string {\n if (utf8DecoderLenient) {\n return utf8DecoderLenient.decode(bytes);\n }\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('utf8');\n }\n return '';\n}\n","import type { CapturedBody } from './types';\nimport { decodeUtf8, encodeBase64, isValidUtf8 } from './encoding';\n\n// eslint-disable-next-line no-control-regex\nconst controlChars = /[\\x00-\\x1F\\x7F]/g;\n\nexport function sanitizeLogString(value: string): string {\n if (!value) {\n return value;\n }\n return value.replace(controlChars, '');\n}\n\nexport function sanitizeHeaderValues(\n headers: Record<string, string | string[]> | undefined,\n): Record<string, string | string[]> | undefined {\n if (!headers) {\n return undefined;\n }\n\n const sanitized: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n const name = sanitizeLogString(key);\n if (Array.isArray(value)) {\n sanitized[name] = value.map((entry) => sanitizeLogString(entry));\n } else {\n sanitized[name] = sanitizeLogString(value);\n }\n }\n return sanitized;\n}\n\nexport function makeCapturedBody(\n bytes: Uint8Array | undefined,\n totalBytes: number,\n truncated: boolean,\n mode: 'text' | 'base64',\n): CapturedBody | undefined {\n if (!bytes) {\n return undefined;\n }\n\n if (mode === 'base64') {\n return {\n bytes: totalBytes,\n encoding: 'base64',\n truncated,\n value: encodeBase64(bytes),\n };\n }\n\n if (isValidUtf8(bytes)) {\n return {\n bytes: totalBytes,\n encoding: 'utf8',\n truncated,\n value: decodeUtf8(bytes),\n };\n }\n\n return {\n bytes: totalBytes,\n encoding: 'base64',\n truncated,\n value: encodeBase64(bytes),\n };\n}\n","import type { Span } from '@opentelemetry/api';\nimport type { AttributeValue, NormalizedRequest, XrayContext } from './types';\nimport type { CaptureConfig, RedactionConfig, ResolvedXrayConfig } from './config';\n\nexport type RequestState = {\n request: NormalizedRequest;\n config: ResolvedXrayConfig;\n span?: Span;\n context: XrayContext;\n attributes: Record<string, AttributeValue>;\n events: Array<{ name: string; attributes?: Record<string, AttributeValue> }>;\n userId?: string;\n sessionId?: string;\n error?: unknown;\n captureOverride?: Partial<CaptureConfig>;\n redactionOverride?: Partial<RedactionConfig>;\n};\n\nconst contextMap = new WeakMap<XrayContext, RequestState>();\nconst objectMap = new WeakMap<object, RequestState>();\n\nexport function bindContext(ctx: XrayContext, state: RequestState): void {\n contextMap.set(ctx, state);\n}\n\nexport function getContextState(ctx: XrayContext): RequestState | undefined {\n return contextMap.get(ctx);\n}\n\nexport function bindObject(target: object, state: RequestState): void {\n objectMap.set(target, state);\n}\n\nexport function getContextFromObject(target: unknown): XrayContext | undefined {\n const state = getStateFromObject(target);\n return state?.context;\n}\n\nexport function getStateFromObject(target: unknown): RequestState | undefined {\n if (!target || typeof target !== 'object') {\n return undefined;\n }\n if (objectMap.has(target)) {\n return objectMap.get(target);\n }\n\n const fallback = findNestedTarget(target as Record<string, unknown>);\n if (fallback && objectMap.has(fallback)) {\n return objectMap.get(fallback);\n }\n return undefined;\n}\n\nfunction findNestedTarget(obj: Record<string, unknown>): object | null {\n if (obj.raw && typeof obj.raw === 'object') {\n return obj.raw as object;\n }\n if (obj.req && typeof obj.req === 'object') {\n const req = obj.req as Record<string, unknown>;\n if (req.raw && typeof req.raw === 'object') {\n return req.raw as object;\n }\n return req as object;\n }\n if (obj.request && typeof obj.request === 'object') {\n const request = obj.request as Record<string, unknown>;\n if (request.raw && typeof request.raw === 'object') {\n return request.raw as object;\n }\n return request as object;\n }\n return null;\n}\n"],"mappings":";AAEA,IAAM,gBAA0C;AAAA,EAC9C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAEO,SAAS,aACd,QACA,OACA,WACA,SACA,QACM;AACN,MAAI,cAAc,KAAK,IAAI,cAAc,SAAS,GAAG;AACnD;AAAA,EACF;AAEA,QAAM,KACJ,OAAO,KAAK,KAAK,OAAO,QAAQ,OAAO,QAAQ,OAAO,SAAS,OAAO,SAAS,QAAQ;AAEzF,MAAI;AACF,OAAG,KAAK,QAAQ,SAAS,MAAM;AAAA,EACjC,QAAQ;AAAA,EAER;AACF;;;AC5BA,IAAM,cACJ,OAAO,gBAAgB,cAAc,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,IAAI;AACnF,IAAM,qBAAqB,OAAO,gBAAgB,cAAc,IAAI,YAAY,OAAO,IAAI;AAC3F,IAAM,cACJ,WAGA;AAEK,SAAS,aAAa,OAA2B;AACtD,MAAI,aAAa;AACf,WAAO,YAAY,KAAK,KAAK,EAAE,SAAS,QAAQ;AAAA,EAClD;AACA,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,SAAS,QAAW;AACtB;AAAA,IACF;AACA,cAAU,OAAO,aAAa,IAAI;AAAA,EACpC;AACA,MAAI,OAAO,SAAS,aAAa;AAC/B,WAAO,KAAK,MAAM;AAAA,EACpB;AACA,SAAO;AACT;AAEO,SAAS,YAAY,OAA4B;AACtD,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AACA,MAAI;AACF,gBAAY,OAAO,KAAK;AACxB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,OAA2B;AACpD,MAAI,oBAAoB;AACtB,WAAO,mBAAmB,OAAO,KAAK;AAAA,EACxC;AACA,MAAI,aAAa;AACf,WAAO,YAAY,KAAK,KAAK,EAAE,SAAS,MAAM;AAAA,EAChD;AACA,SAAO;AACT;;;AC3CA,IAAM,eAAe;AAEd,SAAS,kBAAkB,OAAuB;AACvD,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,SAAO,MAAM,QAAQ,cAAc,EAAE;AACvC;AAEO,SAAS,qBACd,SAC+C;AAC/C,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,YAA+C,CAAC;AACtD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,UAAM,OAAO,kBAAkB,GAAG;AAClC,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,gBAAU,IAAI,IAAI,MAAM,IAAI,CAAC,UAAU,kBAAkB,KAAK,CAAC;AAAA,IACjE,OAAO;AACL,gBAAU,IAAI,IAAI,kBAAkB,KAAK;AAAA,IAC3C;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,iBACd,OACA,YACA,WACA,MAC0B;AAC1B,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,UAAU;AACrB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV;AAAA,MACA,OAAO,aAAa,KAAK;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,YAAY,KAAK,GAAG;AACtB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV;AAAA,MACA,OAAO,WAAW,KAAK;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,UAAU;AAAA,IACV;AAAA,IACA,OAAO,aAAa,KAAK;AAAA,EAC3B;AACF;;;AChDA,IAAM,aAAa,oBAAI,QAAmC;AAC1D,IAAM,YAAY,oBAAI,QAA8B;AAE7C,SAAS,YAAY,KAAkB,OAA2B;AACvE,aAAW,IAAI,KAAK,KAAK;AAC3B;AAEO,SAAS,gBAAgB,KAA4C;AAC1E,SAAO,WAAW,IAAI,GAAG;AAC3B;AAEO,SAAS,WAAW,QAAgB,OAA2B;AACpE,YAAU,IAAI,QAAQ,KAAK;AAC7B;AAEO,SAAS,qBAAqB,QAA0C;AAC7E,QAAM,QAAQ,mBAAmB,MAAM;AACvC,SAAO,OAAO;AAChB;AAEO,SAAS,mBAAmB,QAA2C;AAC5E,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAO;AAAA,EACT;AACA,MAAI,UAAU,IAAI,MAAM,GAAG;AACzB,WAAO,UAAU,IAAI,MAAM;AAAA,EAC7B;AAEA,QAAM,WAAW,iBAAiB,MAAiC;AACnE,MAAI,YAAY,UAAU,IAAI,QAAQ,GAAG;AACvC,WAAO,UAAU,IAAI,QAAQ;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,KAA6C;AACrE,MAAI,IAAI,OAAO,OAAO,IAAI,QAAQ,UAAU;AAC1C,WAAO,IAAI;AAAA,EACb;AACA,MAAI,IAAI,OAAO,OAAO,IAAI,QAAQ,UAAU;AAC1C,UAAM,MAAM,IAAI;AAChB,QAAI,IAAI,OAAO,OAAO,IAAI,QAAQ,UAAU;AAC1C,aAAO,IAAI;AAAA,IACb;AACA,WAAO;AAAA,EACT;AACA,MAAI,IAAI,WAAW,OAAO,IAAI,YAAY,UAAU;AAClD,UAAM,UAAU,IAAI;AACpB,QAAI,QAAQ,OAAO,OAAO,QAAQ,QAAQ,UAAU;AAClD,aAAO,QAAQ;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;","names":[]}