@sentry/core 10.51.0 → 10.53.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.
- package/browser.js +3 -0
- package/build/cjs/browser.js +529 -0
- package/build/cjs/browser.js.map +1 -0
- package/build/cjs/client.js +15 -2
- package/build/cjs/client.js.map +1 -1
- package/build/cjs/fetch.js +7 -4
- package/build/cjs/fetch.js.map +1 -1
- package/build/cjs/index.js +82 -62
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/instrument/console.js +43 -3
- package/build/cjs/instrument/console.js.map +1 -1
- package/build/cjs/integrations/captureconsole.js +2 -2
- package/build/cjs/integrations/captureconsole.js.map +1 -1
- package/build/cjs/integrations/console.js +5 -1
- package/build/cjs/integrations/console.js.map +1 -1
- package/build/cjs/integrations/express/index.js +4 -6
- package/build/cjs/integrations/express/index.js.map +1 -1
- package/build/cjs/integrations/express/utils.js +0 -7
- package/build/cjs/integrations/express/utils.js.map +1 -1
- package/build/cjs/integrations/http/add-outgoing-request-breadcrumb.js +43 -0
- package/build/cjs/integrations/http/add-outgoing-request-breadcrumb.js.map +1 -0
- package/build/cjs/integrations/http/client-patch.js +113 -0
- package/build/cjs/integrations/http/client-patch.js.map +1 -0
- package/build/cjs/integrations/http/client-subscriptions.js +166 -0
- package/build/cjs/integrations/http/client-subscriptions.js.map +1 -0
- package/build/cjs/integrations/http/constants.js +10 -0
- package/build/cjs/integrations/http/constants.js.map +1 -0
- package/build/cjs/integrations/http/double-wrap-warning.js +29 -0
- package/build/cjs/integrations/http/double-wrap-warning.js.map +1 -0
- package/build/cjs/integrations/http/get-outgoing-span-data.js +88 -0
- package/build/cjs/integrations/http/get-outgoing-span-data.js.map +1 -0
- package/build/cjs/integrations/http/get-request-url.js +54 -0
- package/build/cjs/integrations/http/get-request-url.js.map +1 -0
- package/build/cjs/integrations/http/inject-trace-propagation-headers.js +81 -0
- package/build/cjs/integrations/http/inject-trace-propagation-headers.js.map +1 -0
- package/build/cjs/integrations/mcp-server/errorCapture.js +2 -2
- package/build/cjs/integrations/mcp-server/errorCapture.js.map +1 -1
- package/build/cjs/integrations/mcp-server/handlers.js +72 -0
- package/build/cjs/integrations/mcp-server/handlers.js.map +1 -1
- package/build/cjs/integrations/mcp-server/index.js +10 -1
- package/build/cjs/integrations/mcp-server/index.js.map +1 -1
- package/build/cjs/integrations/requestdata.js +85 -3
- package/build/cjs/integrations/requestdata.js.map +1 -1
- package/build/cjs/integrations/supabase.js +4 -4
- package/build/cjs/integrations/supabase.js.map +1 -1
- package/build/cjs/logs/envelope.js +12 -2
- package/build/cjs/logs/envelope.js.map +1 -1
- package/build/cjs/logs/internal.js +7 -1
- package/build/cjs/logs/internal.js.map +1 -1
- package/build/cjs/metrics/envelope.js +15 -2
- package/build/cjs/metrics/envelope.js.map +1 -1
- package/build/cjs/metrics/internal.js +7 -1
- package/build/cjs/metrics/internal.js.map +1 -1
- package/build/cjs/server.js +563 -0
- package/build/cjs/server.js.map +1 -0
- package/build/cjs/tracing/ai/utils.js +2 -2
- package/build/cjs/tracing/ai/utils.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/index.js +3 -3
- package/build/cjs/tracing/anthropic-ai/index.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/streaming.js +3 -3
- package/build/cjs/tracing/anthropic-ai/streaming.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/utils.js +2 -2
- package/build/cjs/tracing/anthropic-ai/utils.js.map +1 -1
- package/build/cjs/tracing/google-genai/index.js +3 -3
- package/build/cjs/tracing/google-genai/index.js.map +1 -1
- package/build/cjs/tracing/google-genai/streaming.js +2 -2
- package/build/cjs/tracing/google-genai/streaming.js.map +1 -1
- package/build/cjs/tracing/langchain/embeddings.js +2 -2
- package/build/cjs/tracing/langchain/embeddings.js.map +1 -1
- package/build/cjs/tracing/langchain/index.js +4 -4
- package/build/cjs/tracing/langchain/index.js.map +1 -1
- package/build/cjs/tracing/langgraph/index.js +3 -3
- package/build/cjs/tracing/langgraph/index.js.map +1 -1
- package/build/cjs/tracing/langgraph/utils.js +2 -2
- package/build/cjs/tracing/langgraph/utils.js.map +1 -1
- package/build/cjs/tracing/openai/index.js +3 -3
- package/build/cjs/tracing/openai/index.js.map +1 -1
- package/build/cjs/tracing/openai/streaming.js +2 -2
- package/build/cjs/tracing/openai/streaming.js.map +1 -1
- package/build/cjs/tracing/sentrySpan.js +5 -0
- package/build/cjs/tracing/sentrySpan.js.map +1 -1
- package/build/cjs/tracing/spans/captureSpan.js +58 -23
- package/build/cjs/tracing/spans/captureSpan.js.map +1 -1
- package/build/cjs/tracing/spans/extractGenAiSpans.js +60 -0
- package/build/cjs/tracing/spans/extractGenAiSpans.js.map +1 -0
- package/build/cjs/tracing/spans/spanJsonToStreamedSpan.js +26 -0
- package/build/cjs/tracing/spans/spanJsonToStreamedSpan.js.map +1 -0
- package/build/cjs/tracing/trace.js +1 -0
- package/build/cjs/tracing/trace.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/constants.js +8 -0
- package/build/cjs/tracing/vercel-ai/constants.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/index.js +99 -15
- package/build/cjs/tracing/vercel-ai/index.js.map +1 -1
- package/build/cjs/trpc.js +3 -3
- package/build/cjs/trpc.js.map +1 -1
- package/build/cjs/utils/baggage.js +73 -0
- package/build/cjs/utils/baggage.js.map +1 -1
- package/build/cjs/utils/chain-and-copy-promiselike.js +1 -0
- package/build/cjs/utils/chain-and-copy-promiselike.js.map +1 -1
- package/build/cjs/utils/exports.js +7 -7
- package/build/cjs/utils/exports.js.map +1 -1
- package/build/cjs/utils/flushIfServerless.js +2 -2
- package/build/cjs/utils/flushIfServerless.js.map +1 -1
- package/build/cjs/utils/get-default-export.js +32 -0
- package/build/cjs/utils/get-default-export.js.map +1 -0
- package/build/cjs/utils/request.js +129 -0
- package/build/cjs/utils/request.js.map +1 -1
- package/build/cjs/utils/spanUtils.js +1 -1
- package/build/cjs/utils/spanUtils.js.map +1 -1
- package/build/cjs/utils/string.js +9 -2
- package/build/cjs/utils/string.js.map +1 -1
- package/build/cjs/utils/traceData.js +2 -2
- package/build/cjs/utils/traceData.js.map +1 -1
- package/build/cjs/utils/version.js +1 -1
- package/build/esm/browser.js +142 -0
- package/build/esm/browser.js.map +1 -0
- package/build/esm/client.js +15 -2
- package/build/esm/client.js.map +1 -1
- package/build/esm/fetch.js +7 -4
- package/build/esm/fetch.js.map +1 -1
- package/build/esm/index.js +20 -15
- package/build/esm/index.js.map +1 -1
- package/build/esm/instrument/console.js +44 -5
- package/build/esm/instrument/console.js.map +1 -1
- package/build/esm/integrations/console.js +6 -2
- package/build/esm/integrations/console.js.map +1 -1
- package/build/esm/integrations/express/index.js +3 -5
- package/build/esm/integrations/express/index.js.map +1 -1
- package/build/esm/integrations/express/utils.js +1 -7
- package/build/esm/integrations/express/utils.js.map +1 -1
- package/build/esm/integrations/http/add-outgoing-request-breadcrumb.js +41 -0
- package/build/esm/integrations/http/add-outgoing-request-breadcrumb.js.map +1 -0
- package/build/esm/integrations/http/client-patch.js +111 -0
- package/build/esm/integrations/http/client-patch.js.map +1 -0
- package/build/esm/integrations/http/client-subscriptions.js +164 -0
- package/build/esm/integrations/http/client-subscriptions.js.map +1 -0
- package/build/esm/integrations/http/constants.js +6 -0
- package/build/esm/integrations/http/constants.js.map +1 -0
- package/build/esm/integrations/http/double-wrap-warning.js +26 -0
- package/build/esm/integrations/http/double-wrap-warning.js.map +1 -0
- package/build/esm/integrations/http/get-outgoing-span-data.js +85 -0
- package/build/esm/integrations/http/get-outgoing-span-data.js.map +1 -0
- package/build/esm/integrations/http/get-request-url.js +49 -0
- package/build/esm/integrations/http/get-request-url.js.map +1 -0
- package/build/esm/integrations/http/inject-trace-propagation-headers.js +79 -0
- package/build/esm/integrations/http/inject-trace-propagation-headers.js.map +1 -0
- package/build/esm/integrations/mcp-server/handlers.js +72 -1
- package/build/esm/integrations/mcp-server/handlers.js.map +1 -1
- package/build/esm/integrations/mcp-server/index.js +11 -2
- package/build/esm/integrations/mcp-server/index.js.map +1 -1
- package/build/esm/integrations/requestdata.js +85 -3
- package/build/esm/integrations/requestdata.js.map +1 -1
- package/build/esm/logs/envelope.js +12 -2
- package/build/esm/logs/envelope.js.map +1 -1
- package/build/esm/logs/internal.js +7 -1
- package/build/esm/logs/internal.js.map +1 -1
- package/build/esm/metrics/envelope.js +15 -2
- package/build/esm/metrics/envelope.js.map +1 -1
- package/build/esm/metrics/internal.js +7 -1
- package/build/esm/metrics/internal.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/server.js +157 -0
- package/build/esm/server.js.map +1 -0
- package/build/esm/tracing/sentrySpan.js +5 -0
- package/build/esm/tracing/sentrySpan.js.map +1 -1
- package/build/esm/tracing/spans/captureSpan.js +58 -23
- package/build/esm/tracing/spans/captureSpan.js.map +1 -1
- package/build/esm/tracing/spans/extractGenAiSpans.js +58 -0
- package/build/esm/tracing/spans/extractGenAiSpans.js.map +1 -0
- package/build/esm/tracing/spans/spanJsonToStreamedSpan.js +24 -0
- package/build/esm/tracing/spans/spanJsonToStreamedSpan.js.map +1 -0
- package/build/esm/tracing/trace.js +1 -1
- package/build/esm/tracing/trace.js.map +1 -1
- package/build/esm/tracing/vercel-ai/constants.js +8 -1
- package/build/esm/tracing/vercel-ai/constants.js.map +1 -1
- package/build/esm/tracing/vercel-ai/index.js +101 -18
- package/build/esm/tracing/vercel-ai/index.js.map +1 -1
- package/build/esm/utils/baggage.js +73 -1
- package/build/esm/utils/baggage.js.map +1 -1
- package/build/esm/utils/chain-and-copy-promiselike.js +1 -0
- package/build/esm/utils/chain-and-copy-promiselike.js.map +1 -1
- package/build/esm/utils/exports.js +7 -7
- package/build/esm/utils/exports.js.map +1 -1
- package/build/esm/utils/get-default-export.js +30 -0
- package/build/esm/utils/get-default-export.js.map +1 -0
- package/build/esm/utils/request.js +127 -1
- package/build/esm/utils/request.js.map +1 -1
- package/build/esm/utils/spanUtils.js +1 -1
- package/build/esm/utils/spanUtils.js.map +1 -1
- package/build/esm/utils/string.js +9 -2
- package/build/esm/utils/string.js.map +1 -1
- package/build/esm/utils/version.js +1 -1
- package/build/types/browser-exports.d.ts +11 -0
- package/build/types/browser-exports.d.ts.map +1 -0
- package/build/types/browser.d.ts +3 -0
- package/build/types/browser.d.ts.map +1 -0
- package/build/types/build-time-plugins/buildTimeOptionsBase.d.ts +8 -0
- package/build/types/build-time-plugins/buildTimeOptionsBase.d.ts.map +1 -1
- package/build/types/carrier.d.ts +1 -1
- package/build/types/carrier.d.ts.map +1 -1
- package/build/types/client.d.ts.map +1 -1
- package/build/types/fetch.d.ts.map +1 -1
- package/build/types/index.d.ts +3 -223
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrument/console.d.ts +7 -0
- package/build/types/instrument/console.d.ts.map +1 -1
- package/build/types/integrations/captureconsole.d.ts +1 -1
- package/build/types/integrations/captureconsole.d.ts.map +1 -1
- package/build/types/integrations/console.d.ts +5 -0
- package/build/types/integrations/console.d.ts.map +1 -1
- package/build/types/integrations/conversationId.d.ts +1 -1
- package/build/types/integrations/conversationId.d.ts.map +1 -1
- package/build/types/integrations/dedupe.d.ts +1 -1
- package/build/types/integrations/dedupe.d.ts.map +1 -1
- package/build/types/integrations/eventFilters.d.ts +2 -2
- package/build/types/integrations/eventFilters.d.ts.map +1 -1
- package/build/types/integrations/express/index.d.ts.map +1 -1
- package/build/types/integrations/express/utils.d.ts +1 -5
- package/build/types/integrations/express/utils.d.ts.map +1 -1
- package/build/types/integrations/extraerrordata.d.ts +1 -1
- package/build/types/integrations/extraerrordata.d.ts.map +1 -1
- package/build/types/integrations/functiontostring.d.ts +1 -1
- package/build/types/integrations/functiontostring.d.ts.map +1 -1
- package/build/types/integrations/http/add-outgoing-request-breadcrumb.d.ts +6 -0
- package/build/types/integrations/http/add-outgoing-request-breadcrumb.d.ts.map +1 -0
- package/build/types/integrations/http/client-patch.d.ts +46 -0
- package/build/types/integrations/http/client-patch.d.ts.map +1 -0
- package/build/types/integrations/http/client-subscriptions.d.ts +21 -0
- package/build/types/integrations/http/client-subscriptions.d.ts.map +1 -0
- package/build/types/integrations/http/constants.d.ts +6 -0
- package/build/types/integrations/http/constants.d.ts.map +1 -0
- package/build/types/integrations/http/double-wrap-warning.d.ts +4 -0
- package/build/types/integrations/http/double-wrap-warning.d.ts.map +1 -0
- package/build/types/integrations/http/get-outgoing-span-data.d.ts +13 -0
- package/build/types/integrations/http/get-outgoing-span-data.d.ts.map +1 -0
- package/build/types/integrations/http/get-request-url.d.ts +10 -0
- package/build/types/integrations/http/get-request-url.d.ts.map +1 -0
- package/build/types/integrations/http/index.d.ts +4 -0
- package/build/types/integrations/http/index.d.ts.map +1 -0
- package/build/types/integrations/http/inject-trace-propagation-headers.d.ts +12 -0
- package/build/types/integrations/http/inject-trace-propagation-headers.d.ts.map +1 -0
- package/build/types/integrations/http/types.d.ts +249 -0
- package/build/types/integrations/http/types.d.ts.map +1 -0
- package/build/types/integrations/linkederrors.d.ts +1 -1
- package/build/types/integrations/linkederrors.d.ts.map +1 -1
- package/build/types/integrations/mcp-server/handlers.d.ts +18 -0
- package/build/types/integrations/mcp-server/handlers.d.ts.map +1 -1
- package/build/types/integrations/mcp-server/index.d.ts +8 -1
- package/build/types/integrations/mcp-server/index.d.ts.map +1 -1
- package/build/types/integrations/requestdata.d.ts +1 -1
- package/build/types/integrations/requestdata.d.ts.map +1 -1
- package/build/types/integrations/spanStreaming.d.ts +1 -1
- package/build/types/integrations/spanStreaming.d.ts.map +1 -1
- package/build/types/integrations/supabase.d.ts +1 -1
- package/build/types/integrations/supabase.d.ts.map +1 -1
- package/build/types/integrations/zoderrors.d.ts +1 -1
- package/build/types/integrations/zoderrors.d.ts.map +1 -1
- package/build/types/logs/console-integration.d.ts +1 -1
- package/build/types/logs/console-integration.d.ts.map +1 -1
- package/build/types/logs/envelope.d.ts +5 -2
- package/build/types/logs/envelope.d.ts.map +1 -1
- package/build/types/logs/internal.d.ts.map +1 -1
- package/build/types/metrics/envelope.d.ts +5 -2
- package/build/types/metrics/envelope.d.ts.map +1 -1
- package/build/types/metrics/internal.d.ts.map +1 -1
- package/build/types/server-exports.d.ts +26 -0
- package/build/types/server-exports.d.ts.map +1 -0
- package/build/types/server.d.ts +10 -0
- package/build/types/server.d.ts.map +1 -0
- package/build/types/shared-exports.d.ts +215 -0
- package/build/types/shared-exports.d.ts.map +1 -0
- package/build/types/tracing/index.d.ts +1 -1
- package/build/types/tracing/index.d.ts.map +1 -1
- package/build/types/tracing/sentrySpan.d.ts.map +1 -1
- package/build/types/tracing/spans/captureSpan.d.ts +4 -4
- package/build/types/tracing/spans/captureSpan.d.ts.map +1 -1
- package/build/types/tracing/spans/extractGenAiSpans.d.ts +15 -0
- package/build/types/tracing/spans/extractGenAiSpans.d.ts.map +1 -0
- package/build/types/tracing/spans/spanJsonToStreamedSpan.d.ts +6 -0
- package/build/types/tracing/spans/spanJsonToStreamedSpan.d.ts.map +1 -0
- package/build/types/tracing/trace.d.ts +1 -0
- package/build/types/tracing/trace.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/constants.d.ts +1 -0
- package/build/types/tracing/vercel-ai/constants.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/index.d.ts +9 -0
- package/build/types/tracing/vercel-ai/index.d.ts.map +1 -1
- package/build/types/types-hoist/envelope.d.ts +1 -1
- package/build/types/types-hoist/envelope.d.ts.map +1 -1
- package/build/types/types-hoist/log.d.ts +5 -0
- package/build/types/types-hoist/log.d.ts.map +1 -1
- package/build/types/types-hoist/metric.d.ts +5 -0
- package/build/types/types-hoist/metric.d.ts.map +1 -1
- package/build/types/types-hoist/options.d.ts +8 -0
- package/build/types/types-hoist/options.d.ts.map +1 -1
- package/build/types/types-hoist/webfetchapi.d.ts +2 -0
- package/build/types/types-hoist/webfetchapi.d.ts.map +1 -1
- package/build/types/utils/baggage.d.ts +13 -0
- package/build/types/utils/baggage.d.ts.map +1 -1
- package/build/types/utils/get-default-export.d.ts +22 -0
- package/build/types/utils/get-default-export.d.ts.map +1 -0
- package/build/types/utils/request.d.ts +30 -0
- package/build/types/utils/request.d.ts.map +1 -1
- package/build/types/utils/spanUtils.d.ts +1 -1
- package/build/types/utils/string.d.ts +1 -1
- package/build/types/utils/string.d.ts.map +1 -1
- package/build/types-ts3.8/browser-exports.d.ts +11 -0
- package/build/types-ts3.8/browser.d.ts +3 -0
- package/build/types-ts3.8/build-time-plugins/buildTimeOptionsBase.d.ts +8 -0
- package/build/types-ts3.8/carrier.d.ts +1 -1
- package/build/types-ts3.8/index.d.ts +3 -225
- package/build/types-ts3.8/instrument/console.d.ts +7 -0
- package/build/types-ts3.8/integrations/captureconsole.d.ts +1 -1
- package/build/types-ts3.8/integrations/console.d.ts +5 -0
- package/build/types-ts3.8/integrations/conversationId.d.ts +1 -1
- package/build/types-ts3.8/integrations/dedupe.d.ts +1 -1
- package/build/types-ts3.8/integrations/eventFilters.d.ts +2 -2
- package/build/types-ts3.8/integrations/express/utils.d.ts +1 -5
- package/build/types-ts3.8/integrations/extraerrordata.d.ts +1 -1
- package/build/types-ts3.8/integrations/functiontostring.d.ts +1 -1
- package/build/types-ts3.8/integrations/http/add-outgoing-request-breadcrumb.d.ts +6 -0
- package/build/types-ts3.8/integrations/http/client-patch.d.ts +46 -0
- package/build/types-ts3.8/integrations/http/client-subscriptions.d.ts +21 -0
- package/build/types-ts3.8/integrations/http/constants.d.ts +6 -0
- package/build/types-ts3.8/integrations/http/double-wrap-warning.d.ts +4 -0
- package/build/types-ts3.8/integrations/http/get-outgoing-span-data.d.ts +13 -0
- package/build/types-ts3.8/integrations/http/get-request-url.d.ts +10 -0
- package/build/types-ts3.8/integrations/http/index.d.ts +4 -0
- package/build/types-ts3.8/integrations/http/inject-trace-propagation-headers.d.ts +12 -0
- package/build/types-ts3.8/integrations/http/types.d.ts +252 -0
- package/build/types-ts3.8/integrations/linkederrors.d.ts +1 -1
- package/build/types-ts3.8/integrations/mcp-server/handlers.d.ts +18 -0
- package/build/types-ts3.8/integrations/mcp-server/index.d.ts +8 -1
- package/build/types-ts3.8/integrations/requestdata.d.ts +1 -1
- package/build/types-ts3.8/integrations/spanStreaming.d.ts +1 -1
- package/build/types-ts3.8/integrations/supabase.d.ts +1 -1
- package/build/types-ts3.8/integrations/zoderrors.d.ts +1 -1
- package/build/types-ts3.8/logs/console-integration.d.ts +1 -1
- package/build/types-ts3.8/logs/envelope.d.ts +5 -2
- package/build/types-ts3.8/metrics/envelope.d.ts +5 -2
- package/build/types-ts3.8/server-exports.d.ts +21 -0
- package/build/types-ts3.8/server.d.ts +10 -0
- package/build/types-ts3.8/shared-exports.d.ts +214 -0
- package/build/types-ts3.8/tracing/index.d.ts +1 -1
- package/build/types-ts3.8/tracing/spans/captureSpan.d.ts +4 -4
- package/build/types-ts3.8/tracing/spans/extractGenAiSpans.d.ts +15 -0
- package/build/types-ts3.8/tracing/spans/spanJsonToStreamedSpan.d.ts +6 -0
- package/build/types-ts3.8/tracing/trace.d.ts +1 -0
- package/build/types-ts3.8/tracing/vercel-ai/constants.d.ts +1 -0
- package/build/types-ts3.8/tracing/vercel-ai/index.d.ts +9 -0
- package/build/types-ts3.8/types-hoist/envelope.d.ts +1 -1
- package/build/types-ts3.8/types-hoist/log.d.ts +5 -0
- package/build/types-ts3.8/types-hoist/metric.d.ts +5 -0
- package/build/types-ts3.8/types-hoist/options.d.ts +8 -0
- package/build/types-ts3.8/types-hoist/webfetchapi.d.ts +2 -0
- package/build/types-ts3.8/utils/baggage.d.ts +13 -0
- package/build/types-ts3.8/utils/get-default-export.d.ts +22 -0
- package/build/types-ts3.8/utils/request.d.ts +30 -0
- package/build/types-ts3.8/utils/spanUtils.d.ts +1 -1
- package/build/types-ts3.8/utils/string.d.ts +1 -1
- package/package.json +24 -2
- package/server.js +3 -0
package/build/cjs/trpc.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const currentScopes = require('./currentScopes.js');
|
|
4
|
-
const
|
|
4
|
+
const exports$1 = require('./exports.js');
|
|
5
5
|
const semanticAttributes = require('./semanticAttributes.js');
|
|
6
6
|
const normalize = require('./utils/normalize.js');
|
|
7
7
|
const trace = require('./tracing/trace.js');
|
|
@@ -18,7 +18,7 @@ function captureIfError(nextResult) {
|
|
|
18
18
|
!nextResult.ok &&
|
|
19
19
|
'error' in nextResult
|
|
20
20
|
) {
|
|
21
|
-
|
|
21
|
+
exports$1.captureException(nextResult.error, trpcCaptureContext);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -80,7 +80,7 @@ function trpcMiddleware(options = {}) {
|
|
|
80
80
|
span.end();
|
|
81
81
|
return nextResult;
|
|
82
82
|
} catch (e) {
|
|
83
|
-
|
|
83
|
+
exports$1.captureException(e, trpcCaptureContext);
|
|
84
84
|
span.end();
|
|
85
85
|
throw e;
|
|
86
86
|
}
|
package/build/cjs/trpc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trpc.js","sources":["../../src/trpc.ts"],"sourcesContent":["import { getClient, withIsolationScope } from './currentScopes';\nimport { captureException } from './exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from './semanticAttributes';\nimport { startSpanManual } from './tracing';\nimport { normalize } from './utils/normalize';\nimport { setNormalizationDepthOverrideHint } from './utils/normalizationHints';\n\ninterface SentryTrpcMiddlewareOptions {\n /** Whether to include procedure inputs in reported events. Defaults to `false`. */\n attachRpcInput?: boolean;\n forceTransaction?: boolean;\n}\n\nexport interface SentryTrpcMiddlewareArguments<T> {\n path?: unknown;\n type?: unknown;\n next: () => T;\n rawInput?: unknown;\n getRawInput?: () => Promise<unknown>;\n}\n\nconst trpcCaptureContext = { mechanism: { handled: false, type: 'auto.rpc.trpc.middleware' } };\n\nfunction captureIfError(nextResult: unknown): void {\n // TODO: Set span status based on what TRPCError was encountered\n if (\n typeof nextResult === 'object' &&\n nextResult !== null &&\n 'ok' in nextResult &&\n !nextResult.ok &&\n 'error' in nextResult\n ) {\n captureException(nextResult.error, trpcCaptureContext);\n }\n}\n\ntype SentryTrpcMiddleware<T> = T extends Promise<unknown> ? T : Promise<T>;\n\n/**\n * Sentry tRPC middleware that captures errors and creates spans for tRPC procedures.\n */\nexport function trpcMiddleware(options: SentryTrpcMiddlewareOptions = {}) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return async function <T>(opts: SentryTrpcMiddlewareArguments<T>): SentryTrpcMiddleware<T> {\n const { path, type, next, rawInput, getRawInput } = opts;\n\n const client = getClient();\n const clientOptions = client?.getOptions();\n\n const trpcContext: Record<string, unknown> = {\n procedure_path: path,\n procedure_type: type,\n };\n\n setNormalizationDepthOverrideHint(\n trpcContext,\n 1 + // 1 for context.input + the normal normalization depth\n (clientOptions?.normalizeDepth ?? 5), // 5 is a sane depth\n );\n\n if (options.attachRpcInput !== undefined ? options.attachRpcInput : clientOptions?.sendDefaultPii) {\n if (rawInput !== undefined) {\n trpcContext.input = normalize(rawInput);\n }\n\n if (getRawInput !== undefined && typeof getRawInput === 'function') {\n try {\n const rawRes = await getRawInput();\n\n trpcContext.input = normalize(rawRes);\n } catch {\n // noop\n }\n }\n }\n\n return withIsolationScope(scope => {\n scope.setContext('trpc', trpcContext);\n return startSpanManual(\n {\n name: `trpc/${path}`,\n op: 'rpc.server',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.rpc.trpc',\n },\n forceTransaction: !!options.forceTransaction,\n },\n async span => {\n try {\n const nextResult = await next();\n captureIfError(nextResult);\n span.end();\n return nextResult;\n } catch (e) {\n captureException(e, trpcCaptureContext);\n span.end();\n throw e;\n }\n },\n ) as SentryTrpcMiddleware<T>;\n });\n };\n}\n"],"names":["captureException","getClient","setNormalizationDepthOverrideHint","normalize","withIsolationScope","startSpanManual","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":";;;;;;;;;AAqBA,MAAM,kBAAA,GAAqB,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,0BAAA,IAA8B;;AAE9F,SAAS,cAAc,CAAC,UAAU,EAAiB;AACnD;AACA,EAAE;AACF,IAAI,OAAO,UAAA,KAAe,QAAA;AAC1B,IAAI,UAAA,KAAe,IAAA;AACnB,IAAI,IAAA,IAAQ,UAAA;AACZ,IAAI,CAAC,UAAU,CAAC,EAAA;AAChB,IAAI,WAAW;AACf,IAAI;AACJ,IAAIA,
|
|
1
|
+
{"version":3,"file":"trpc.js","sources":["../../src/trpc.ts"],"sourcesContent":["import { getClient, withIsolationScope } from './currentScopes';\nimport { captureException } from './exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from './semanticAttributes';\nimport { startSpanManual } from './tracing';\nimport { normalize } from './utils/normalize';\nimport { setNormalizationDepthOverrideHint } from './utils/normalizationHints';\n\ninterface SentryTrpcMiddlewareOptions {\n /** Whether to include procedure inputs in reported events. Defaults to `false`. */\n attachRpcInput?: boolean;\n forceTransaction?: boolean;\n}\n\nexport interface SentryTrpcMiddlewareArguments<T> {\n path?: unknown;\n type?: unknown;\n next: () => T;\n rawInput?: unknown;\n getRawInput?: () => Promise<unknown>;\n}\n\nconst trpcCaptureContext = { mechanism: { handled: false, type: 'auto.rpc.trpc.middleware' } };\n\nfunction captureIfError(nextResult: unknown): void {\n // TODO: Set span status based on what TRPCError was encountered\n if (\n typeof nextResult === 'object' &&\n nextResult !== null &&\n 'ok' in nextResult &&\n !nextResult.ok &&\n 'error' in nextResult\n ) {\n captureException(nextResult.error, trpcCaptureContext);\n }\n}\n\ntype SentryTrpcMiddleware<T> = T extends Promise<unknown> ? T : Promise<T>;\n\n/**\n * Sentry tRPC middleware that captures errors and creates spans for tRPC procedures.\n */\nexport function trpcMiddleware(options: SentryTrpcMiddlewareOptions = {}) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return async function <T>(opts: SentryTrpcMiddlewareArguments<T>): SentryTrpcMiddleware<T> {\n const { path, type, next, rawInput, getRawInput } = opts;\n\n const client = getClient();\n const clientOptions = client?.getOptions();\n\n const trpcContext: Record<string, unknown> = {\n procedure_path: path,\n procedure_type: type,\n };\n\n setNormalizationDepthOverrideHint(\n trpcContext,\n 1 + // 1 for context.input + the normal normalization depth\n (clientOptions?.normalizeDepth ?? 5), // 5 is a sane depth\n );\n\n if (options.attachRpcInput !== undefined ? options.attachRpcInput : clientOptions?.sendDefaultPii) {\n if (rawInput !== undefined) {\n trpcContext.input = normalize(rawInput);\n }\n\n if (getRawInput !== undefined && typeof getRawInput === 'function') {\n try {\n const rawRes = await getRawInput();\n\n trpcContext.input = normalize(rawRes);\n } catch {\n // noop\n }\n }\n }\n\n return withIsolationScope(scope => {\n scope.setContext('trpc', trpcContext);\n return startSpanManual(\n {\n name: `trpc/${path}`,\n op: 'rpc.server',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.rpc.trpc',\n },\n forceTransaction: !!options.forceTransaction,\n },\n async span => {\n try {\n const nextResult = await next();\n captureIfError(nextResult);\n span.end();\n return nextResult;\n } catch (e) {\n captureException(e, trpcCaptureContext);\n span.end();\n throw e;\n }\n },\n ) as SentryTrpcMiddleware<T>;\n });\n };\n}\n"],"names":["captureException","getClient","setNormalizationDepthOverrideHint","normalize","withIsolationScope","startSpanManual","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":";;;;;;;;;AAqBA,MAAM,kBAAA,GAAqB,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,0BAAA,IAA8B;;AAE9F,SAAS,cAAc,CAAC,UAAU,EAAiB;AACnD;AACA,EAAE;AACF,IAAI,OAAO,UAAA,KAAe,QAAA;AAC1B,IAAI,UAAA,KAAe,IAAA;AACnB,IAAI,IAAA,IAAQ,UAAA;AACZ,IAAI,CAAC,UAAU,CAAC,EAAA;AAChB,IAAI,WAAW;AACf,IAAI;AACJ,IAAIA,0BAAgB,CAAC,UAAU,CAAC,KAAK,EAAE,kBAAkB,CAAC;AAC1D,EAAE;AACF;;AAIA;AACA;AACA;AACO,SAAS,cAAc,CAAC,OAAO,GAAgC,EAAE,EAAE;AAC1E;AACA;AACA,EAAE,OAAO,gBAAmB,IAAI,EAA6D;AAC7F,IAAI,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAA,EAAY,GAAI,IAAI;;AAE5D,IAAI,MAAM,MAAA,GAASC,uBAAS,EAAE;AAC9B,IAAI,MAAM,aAAA,GAAgB,MAAM,EAAE,UAAU,EAAE;;AAE9C,IAAI,MAAM,WAAW,GAA4B;AACjD,MAAM,cAAc,EAAE,IAAI;AAC1B,MAAM,cAAc,EAAE,IAAI;AAC1B,KAAK;;AAEL,IAAIC,oDAAiC;AACrC,MAAM,WAAW;AACjB,MAAM,CAAA;AACN,SAAS,aAAa,EAAE,cAAA,IAAkB,CAAC,CAAC;AAC5C,KAAK;;AAEL,IAAI,IAAI,OAAO,CAAC,mBAAmB,SAAA,GAAY,OAAO,CAAC,cAAA,GAAiB,aAAa,EAAE,cAAc,EAAE;AACvG,MAAM,IAAI,QAAA,KAAa,SAAS,EAAE;AAClC,QAAQ,WAAW,CAAC,KAAA,GAAQC,mBAAS,CAAC,QAAQ,CAAC;AAC/C,MAAM;;AAEN,MAAM,IAAI,WAAA,KAAgB,SAAA,IAAa,OAAO,WAAA,KAAgB,UAAU,EAAE;AAC1E,QAAQ,IAAI;AACZ,UAAU,MAAM,MAAA,GAAS,MAAM,WAAW,EAAE;;AAE5C,UAAU,WAAW,CAAC,KAAA,GAAQA,mBAAS,CAAC,MAAM,CAAC;AAC/C,QAAQ,EAAE,MAAM;AAChB;AACA,QAAQ;AACR,MAAM;AACN,IAAI;;AAEJ,IAAI,OAAOC,gCAAkB,CAAC,KAAA,IAAS;AACvC,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC;AAC3C,MAAM,OAAOC,qBAAe;AAC5B,QAAQ;AACR,UAAU,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;AACA,UAAA,EAAA,EAAA,YAAA;AACA,UAAA,UAAA,EAAA;AACA,YAAA,CAAAC,mDAAA,GAAA,OAAA;AACA,YAAA,CAAAC,mDAAA,GAAA,eAAA;AACA,WAAA;AACA,UAAA,gBAAA,EAAA,CAAA,CAAA,OAAA,CAAA,gBAAA;AACA,SAAA;AACA,QAAA,MAAA,IAAA,IAAA;AACA,UAAA,IAAA;AACA,YAAA,MAAA,UAAA,GAAA,MAAA,IAAA,EAAA;AACA,YAAA,cAAA,CAAA,UAAA,CAAA;AACA,YAAA,IAAA,CAAA,GAAA,EAAA;AACA,YAAA,OAAA,UAAA;AACA,UAAA,CAAA,CAAA,OAAA,CAAA,EAAA;AACA,YAAAP,0BAAA,CAAA,CAAA,EAAA,kBAAA,CAAA;AACA,YAAA,IAAA,CAAA,GAAA,EAAA;AACA,YAAA,MAAA,CAAA;AACA,UAAA;AACA,QAAA,CAAA;AACA,OAAA;AACA,IAAA,CAAA,CAAA;AACA,EAAA,CAAA;AACA;;;;"}
|
|
@@ -168,11 +168,84 @@ function objectToBaggageHeader(object) {
|
|
|
168
168
|
}, '');
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Merge two baggage headers into one.
|
|
173
|
+
* - Sentry-specific entries (keys starting with "sentry-") from the new
|
|
174
|
+
* baggage take precedence
|
|
175
|
+
* - Non-Sentry entries from existing baggage take precedence
|
|
176
|
+
*
|
|
177
|
+
* The order of the existing baggage will be preserved, and new entries will
|
|
178
|
+
* be added to the end.
|
|
179
|
+
*
|
|
180
|
+
* This matches the behavior of OTEL's propagation.inject() which uses
|
|
181
|
+
* `baggage.setEntry()` to overwrite existing entries with the same key.
|
|
182
|
+
*/
|
|
183
|
+
function mergeBaggageHeaders(
|
|
184
|
+
existing,
|
|
185
|
+
incoming,
|
|
186
|
+
) {
|
|
187
|
+
if (!existing) {
|
|
188
|
+
return incoming;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const existingEntries = parseBaggageHeader(existing);
|
|
192
|
+
const incomingEntries = parseBaggageHeader(incoming);
|
|
193
|
+
|
|
194
|
+
if (!incomingEntries) {
|
|
195
|
+
return existing;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 1. All non-sentry entries from existing are kept
|
|
199
|
+
// 2. All sentry- entries from the new baggage are retained
|
|
200
|
+
// 3. If sentry- entries present in new, ignore from old, else keep from old.
|
|
201
|
+
// 4. Non-sentry entries from new are only kept if not in existing.
|
|
202
|
+
|
|
203
|
+
const merged = {};
|
|
204
|
+
|
|
205
|
+
// partition incoming entries into sentry and non-sentry prefixed
|
|
206
|
+
let hasNewSentryEntries = false;
|
|
207
|
+
const newSentryEntries = {};
|
|
208
|
+
const newNonSentryEntries = {};
|
|
209
|
+
for (const [key, value] of Object.entries(incomingEntries)) {
|
|
210
|
+
if (key.startsWith(SENTRY_BAGGAGE_KEY_PREFIX)) {
|
|
211
|
+
newSentryEntries[key] = value;
|
|
212
|
+
hasNewSentryEntries = true;
|
|
213
|
+
} else {
|
|
214
|
+
newNonSentryEntries[key] = value;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// If new baggage contains at least one sentry- value, we remove all old
|
|
219
|
+
// sentry- values otherwise, we keep old sentry- values. If we don't remove
|
|
220
|
+
// old sentry- values, we end up with an inconsistent dynamic sampling
|
|
221
|
+
// context propagation.
|
|
222
|
+
if (existingEntries) {
|
|
223
|
+
for (const [key, value] of Object.entries(existingEntries)) {
|
|
224
|
+
if (!hasNewSentryEntries || !key.startsWith(SENTRY_BAGGAGE_KEY_PREFIX)) {
|
|
225
|
+
merged[key] = value;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Assign new sentry fields.
|
|
231
|
+
if (hasNewSentryEntries) {
|
|
232
|
+
Object.assign(merged, newSentryEntries);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// assign new non-sentry fields not found on existing object.
|
|
236
|
+
for (const [key, value] of Object.entries(newNonSentryEntries)) {
|
|
237
|
+
merged[key] ??= value;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return objectToBaggageHeader(merged);
|
|
241
|
+
}
|
|
242
|
+
|
|
171
243
|
exports.MAX_BAGGAGE_STRING_LENGTH = MAX_BAGGAGE_STRING_LENGTH;
|
|
172
244
|
exports.SENTRY_BAGGAGE_KEY_PREFIX = SENTRY_BAGGAGE_KEY_PREFIX;
|
|
173
245
|
exports.SENTRY_BAGGAGE_KEY_PREFIX_REGEX = SENTRY_BAGGAGE_KEY_PREFIX_REGEX;
|
|
174
246
|
exports.baggageHeaderToDynamicSamplingContext = baggageHeaderToDynamicSamplingContext;
|
|
175
247
|
exports.dynamicSamplingContextToSentryBaggageHeader = dynamicSamplingContextToSentryBaggageHeader;
|
|
248
|
+
exports.mergeBaggageHeaders = mergeBaggageHeaders;
|
|
176
249
|
exports.objectToBaggageHeader = objectToBaggageHeader;
|
|
177
250
|
exports.parseBaggageHeader = parseBaggageHeader;
|
|
178
251
|
//# sourceMappingURL=baggage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baggage.js","sources":["../../../src/utils/baggage.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../debug-build';\nimport type { DynamicSamplingContext } from '../types-hoist/envelope';\nimport { debug } from './debug-logger';\nimport { isString } from './is';\n\nexport const SENTRY_BAGGAGE_KEY_PREFIX = 'sentry-';\n\nexport const SENTRY_BAGGAGE_KEY_PREFIX_REGEX = /^sentry-/;\n\n/**\n * Max length of a serialized baggage string\n *\n * https://www.w3.org/TR/baggage/#limits\n */\nexport const MAX_BAGGAGE_STRING_LENGTH = 8192;\n\n/**\n * Takes a baggage header and turns it into Dynamic Sampling Context, by extracting all the \"sentry-\" prefixed values\n * from it.\n *\n * @param baggageHeader A very bread definition of a baggage header as it might appear in various frameworks.\n * @returns The Dynamic Sampling Context that was found on `baggageHeader`, if there was any, `undefined` otherwise.\n */\nexport function baggageHeaderToDynamicSamplingContext(\n // Very liberal definition of what any incoming header might look like\n baggageHeader: string | string[] | number | null | undefined | boolean,\n): Partial<DynamicSamplingContext> | undefined {\n const baggageObject = parseBaggageHeader(baggageHeader);\n\n if (!baggageObject) {\n return undefined;\n }\n\n // Read all \"sentry-\" prefixed values out of the baggage object and put it onto a dynamic sampling context object.\n const dynamicSamplingContext = Object.entries(baggageObject).reduce<Record<string, string>>((acc, [key, value]) => {\n if (key.startsWith(SENTRY_BAGGAGE_KEY_PREFIX)) {\n const nonPrefixedKey = key.slice(SENTRY_BAGGAGE_KEY_PREFIX.length);\n acc[nonPrefixedKey] = value;\n }\n return acc;\n }, {});\n\n // Only return a dynamic sampling context object if there are keys in it.\n // A keyless object means there were no sentry values on the header, which means that there is no DSC.\n if (Object.keys(dynamicSamplingContext).length > 0) {\n return dynamicSamplingContext as Partial<DynamicSamplingContext>;\n } else {\n return undefined;\n }\n}\n\n/**\n * Turns a Dynamic Sampling Object into a baggage header by prefixing all the keys on the object with \"sentry-\".\n *\n * @param dynamicSamplingContext The Dynamic Sampling Context to turn into a header. For convenience and compatibility\n * with the `getDynamicSamplingContext` method on the Transaction class ,this argument can also be `undefined`. If it is\n * `undefined` the function will return `undefined`.\n * @returns a baggage header, created from `dynamicSamplingContext`, or `undefined` either if `dynamicSamplingContext`\n * was `undefined`, or if `dynamicSamplingContext` didn't contain any values.\n */\nexport function dynamicSamplingContextToSentryBaggageHeader(\n // this also takes undefined for convenience and bundle size in other places\n dynamicSamplingContext?: Partial<DynamicSamplingContext>,\n): string | undefined {\n if (!dynamicSamplingContext) {\n return undefined;\n }\n\n // Prefix all DSC keys with \"sentry-\" and put them into a new object\n const sentryPrefixedDSC = Object.entries(dynamicSamplingContext).reduce<Record<string, string>>(\n (acc, [dscKey, dscValue]) => {\n if (dscValue) {\n acc[`${SENTRY_BAGGAGE_KEY_PREFIX}${dscKey}`] = dscValue;\n }\n return acc;\n },\n {},\n );\n\n return objectToBaggageHeader(sentryPrefixedDSC);\n}\n\n/**\n * Take a baggage header and parse it into an object.\n */\nexport function parseBaggageHeader(\n baggageHeader: string | string[] | number | null | undefined | boolean,\n): Record<string, string> | undefined {\n if (!baggageHeader || (!isString(baggageHeader) && !Array.isArray(baggageHeader))) {\n return undefined;\n }\n\n if (Array.isArray(baggageHeader)) {\n // Combine all baggage headers into one object containing the baggage values so we can later read the Sentry-DSC-values from it\n return baggageHeader.reduce<Record<string, string>>((acc, curr) => {\n const currBaggageObject = baggageHeaderToObject(curr);\n Object.entries(currBaggageObject).forEach(([key, value]) => {\n acc[key] = value;\n });\n return acc;\n }, {});\n }\n\n return baggageHeaderToObject(baggageHeader);\n}\n\n/**\n * Will parse a baggage header, which is a simple key-value map, into a flat object.\n *\n * @param baggageHeader The baggage header to parse.\n * @returns a flat object containing all the key-value pairs from `baggageHeader`.\n */\nfunction baggageHeaderToObject(baggageHeader: string): Record<string, string> {\n return baggageHeader\n .split(',')\n .map(baggageEntry => {\n const eqIdx = baggageEntry.indexOf('=');\n if (eqIdx === -1) {\n // Likely an invalid entry\n return [];\n }\n const key = baggageEntry.slice(0, eqIdx);\n const value = baggageEntry.slice(eqIdx + 1);\n return [key, value].map(keyOrValue => {\n try {\n return decodeURIComponent(keyOrValue.trim());\n } catch {\n // We ignore errors here, e.g. if the value cannot be URL decoded.\n // This will then be skipped in the next step\n return;\n }\n });\n })\n .reduce<Record<string, string>>((acc, [key, value]) => {\n if (key && value) {\n acc[key] = value;\n }\n return acc;\n }, {});\n}\n\n/**\n * Turns a flat object (key-value pairs) into a baggage header, which is also just key-value pairs.\n *\n * @param object The object to turn into a baggage header.\n * @returns a baggage header string, or `undefined` if the object didn't have any values, since an empty baggage header\n * is not spec compliant.\n */\nexport function objectToBaggageHeader(object: Record<string, string>): string | undefined {\n if (Object.keys(object).length === 0) {\n // An empty baggage header is not spec compliant: We return undefined.\n return undefined;\n }\n\n return Object.entries(object).reduce((baggageHeader, [objectKey, objectValue], currentIndex) => {\n const baggageEntry = `${encodeURIComponent(objectKey)}=${encodeURIComponent(objectValue)}`;\n const newBaggageHeader = currentIndex === 0 ? baggageEntry : `${baggageHeader},${baggageEntry}`;\n if (newBaggageHeader.length > MAX_BAGGAGE_STRING_LENGTH) {\n DEBUG_BUILD &&\n debug.warn(\n `Not adding key: ${objectKey} with val: ${objectValue} to baggage header due to exceeding baggage size limits.`,\n );\n return baggageHeader;\n } else {\n return newBaggageHeader;\n }\n }, '');\n}\n"],"names":["isString","DEBUG_BUILD","debug"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"baggage.js","sources":["../../../src/utils/baggage.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../debug-build';\nimport type { DynamicSamplingContext } from '../types-hoist/envelope';\nimport { debug } from './debug-logger';\nimport { isString } from './is';\n\nexport const SENTRY_BAGGAGE_KEY_PREFIX = 'sentry-';\n\nexport const SENTRY_BAGGAGE_KEY_PREFIX_REGEX = /^sentry-/;\n\n/**\n * Max length of a serialized baggage string\n *\n * https://www.w3.org/TR/baggage/#limits\n */\nexport const MAX_BAGGAGE_STRING_LENGTH = 8192;\n\n/**\n * Takes a baggage header and turns it into Dynamic Sampling Context, by extracting all the \"sentry-\" prefixed values\n * from it.\n *\n * @param baggageHeader A very bread definition of a baggage header as it might appear in various frameworks.\n * @returns The Dynamic Sampling Context that was found on `baggageHeader`, if there was any, `undefined` otherwise.\n */\nexport function baggageHeaderToDynamicSamplingContext(\n // Very liberal definition of what any incoming header might look like\n baggageHeader: string | string[] | number | null | undefined | boolean,\n): Partial<DynamicSamplingContext> | undefined {\n const baggageObject = parseBaggageHeader(baggageHeader);\n\n if (!baggageObject) {\n return undefined;\n }\n\n // Read all \"sentry-\" prefixed values out of the baggage object and put it onto a dynamic sampling context object.\n const dynamicSamplingContext = Object.entries(baggageObject).reduce<Record<string, string>>((acc, [key, value]) => {\n if (key.startsWith(SENTRY_BAGGAGE_KEY_PREFIX)) {\n const nonPrefixedKey = key.slice(SENTRY_BAGGAGE_KEY_PREFIX.length);\n acc[nonPrefixedKey] = value;\n }\n return acc;\n }, {});\n\n // Only return a dynamic sampling context object if there are keys in it.\n // A keyless object means there were no sentry values on the header, which means that there is no DSC.\n if (Object.keys(dynamicSamplingContext).length > 0) {\n return dynamicSamplingContext as Partial<DynamicSamplingContext>;\n } else {\n return undefined;\n }\n}\n\n/**\n * Turns a Dynamic Sampling Object into a baggage header by prefixing all the keys on the object with \"sentry-\".\n *\n * @param dynamicSamplingContext The Dynamic Sampling Context to turn into a header. For convenience and compatibility\n * with the `getDynamicSamplingContext` method on the Transaction class ,this argument can also be `undefined`. If it is\n * `undefined` the function will return `undefined`.\n * @returns a baggage header, created from `dynamicSamplingContext`, or `undefined` either if `dynamicSamplingContext`\n * was `undefined`, or if `dynamicSamplingContext` didn't contain any values.\n */\nexport function dynamicSamplingContextToSentryBaggageHeader(\n // this also takes undefined for convenience and bundle size in other places\n dynamicSamplingContext?: Partial<DynamicSamplingContext>,\n): string | undefined {\n if (!dynamicSamplingContext) {\n return undefined;\n }\n\n // Prefix all DSC keys with \"sentry-\" and put them into a new object\n const sentryPrefixedDSC = Object.entries(dynamicSamplingContext).reduce<Record<string, string>>(\n (acc, [dscKey, dscValue]) => {\n if (dscValue) {\n acc[`${SENTRY_BAGGAGE_KEY_PREFIX}${dscKey}`] = dscValue;\n }\n return acc;\n },\n {},\n );\n\n return objectToBaggageHeader(sentryPrefixedDSC);\n}\n\n/**\n * Take a baggage header and parse it into an object.\n */\nexport function parseBaggageHeader(\n baggageHeader: string | string[] | number | null | undefined | boolean,\n): Record<string, string> | undefined {\n if (!baggageHeader || (!isString(baggageHeader) && !Array.isArray(baggageHeader))) {\n return undefined;\n }\n\n if (Array.isArray(baggageHeader)) {\n // Combine all baggage headers into one object containing the baggage values so we can later read the Sentry-DSC-values from it\n return baggageHeader.reduce<Record<string, string>>((acc, curr) => {\n const currBaggageObject = baggageHeaderToObject(curr);\n Object.entries(currBaggageObject).forEach(([key, value]) => {\n acc[key] = value;\n });\n return acc;\n }, {});\n }\n\n return baggageHeaderToObject(baggageHeader);\n}\n\n/**\n * Will parse a baggage header, which is a simple key-value map, into a flat object.\n *\n * @param baggageHeader The baggage header to parse.\n * @returns a flat object containing all the key-value pairs from `baggageHeader`.\n */\nfunction baggageHeaderToObject(baggageHeader: string): Record<string, string> {\n return baggageHeader\n .split(',')\n .map(baggageEntry => {\n const eqIdx = baggageEntry.indexOf('=');\n if (eqIdx === -1) {\n // Likely an invalid entry\n return [];\n }\n const key = baggageEntry.slice(0, eqIdx);\n const value = baggageEntry.slice(eqIdx + 1);\n return [key, value].map(keyOrValue => {\n try {\n return decodeURIComponent(keyOrValue.trim());\n } catch {\n // We ignore errors here, e.g. if the value cannot be URL decoded.\n // This will then be skipped in the next step\n return;\n }\n });\n })\n .reduce<Record<string, string>>((acc, [key, value]) => {\n if (key && value) {\n acc[key] = value;\n }\n return acc;\n }, {});\n}\n\n/**\n * Turns a flat object (key-value pairs) into a baggage header, which is also just key-value pairs.\n *\n * @param object The object to turn into a baggage header.\n * @returns a baggage header string, or `undefined` if the object didn't have any values, since an empty baggage header\n * is not spec compliant.\n */\nexport function objectToBaggageHeader(object: Record<string, string>): string | undefined {\n if (Object.keys(object).length === 0) {\n // An empty baggage header is not spec compliant: We return undefined.\n return undefined;\n }\n\n return Object.entries(object).reduce((baggageHeader, [objectKey, objectValue], currentIndex) => {\n const baggageEntry = `${encodeURIComponent(objectKey)}=${encodeURIComponent(objectValue)}`;\n const newBaggageHeader = currentIndex === 0 ? baggageEntry : `${baggageHeader},${baggageEntry}`;\n if (newBaggageHeader.length > MAX_BAGGAGE_STRING_LENGTH) {\n DEBUG_BUILD &&\n debug.warn(\n `Not adding key: ${objectKey} with val: ${objectValue} to baggage header due to exceeding baggage size limits.`,\n );\n return baggageHeader;\n } else {\n return newBaggageHeader;\n }\n }, '');\n}\n\n/**\n * Merge two baggage headers into one.\n * - Sentry-specific entries (keys starting with \"sentry-\") from the new\n * baggage take precedence\n * - Non-Sentry entries from existing baggage take precedence\n *\n * The order of the existing baggage will be preserved, and new entries will\n * be added to the end.\n *\n * This matches the behavior of OTEL's propagation.inject() which uses\n * `baggage.setEntry()` to overwrite existing entries with the same key.\n */\nexport function mergeBaggageHeaders<Existing extends string | string[] | number | undefined>(\n existing: Existing,\n incoming: string,\n): string | undefined | Existing {\n if (!existing) {\n return incoming;\n }\n\n const existingEntries = parseBaggageHeader(existing);\n const incomingEntries = parseBaggageHeader(incoming);\n\n if (!incomingEntries) {\n return existing;\n }\n\n // 1. All non-sentry entries from existing are kept\n // 2. All sentry- entries from the new baggage are retained\n // 3. If sentry- entries present in new, ignore from old, else keep from old.\n // 4. Non-sentry entries from new are only kept if not in existing.\n\n const merged: Record<string, string> = {};\n\n // partition incoming entries into sentry and non-sentry prefixed\n let hasNewSentryEntries = false;\n const newSentryEntries: Record<string, string> = {};\n const newNonSentryEntries: Record<string, string> = {};\n for (const [key, value] of Object.entries(incomingEntries)) {\n if (key.startsWith(SENTRY_BAGGAGE_KEY_PREFIX)) {\n newSentryEntries[key] = value;\n hasNewSentryEntries = true;\n } else {\n newNonSentryEntries[key] = value;\n }\n }\n\n // If new baggage contains at least one sentry- value, we remove all old\n // sentry- values otherwise, we keep old sentry- values. If we don't remove\n // old sentry- values, we end up with an inconsistent dynamic sampling\n // context propagation.\n if (existingEntries) {\n for (const [key, value] of Object.entries(existingEntries)) {\n if (!hasNewSentryEntries || !key.startsWith(SENTRY_BAGGAGE_KEY_PREFIX)) {\n merged[key] = value;\n }\n }\n }\n\n // Assign new sentry fields.\n if (hasNewSentryEntries) {\n Object.assign(merged, newSentryEntries);\n }\n\n // assign new non-sentry fields not found on existing object.\n for (const [key, value] of Object.entries(newNonSentryEntries)) {\n merged[key] ??= value;\n }\n\n return objectToBaggageHeader(merged);\n}\n"],"names":["isString","DEBUG_BUILD","debug"],"mappings":"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"}
|
|
@@ -31,6 +31,7 @@ const chainAndCopyPromiseLike = (
|
|
|
31
31
|
|
|
32
32
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
33
|
const copyProps = (original, chained) => {
|
|
34
|
+
if (!chained) return original;
|
|
34
35
|
let mutated = false;
|
|
35
36
|
//oxlint-disable-next-line guard-for-in
|
|
36
37
|
for (const key in original) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chain-and-copy-promiselike.js","sources":["../../../src/utils/chain-and-copy-promiselike.ts"],"sourcesContent":["const isActualPromise = (p: unknown) =>\n p instanceof Promise && !(p as unknown as ChainedPromiseLike<unknown>)[kChainedCopy];\n\ntype ChainedPromiseLike<T> = PromiseLike<T> & {\n [kChainedCopy]: true;\n};\nconst kChainedCopy = Symbol('chained PromiseLike');\n\n/**\n * Copy the properties from a decorated promiselike object onto its chained\n * actual promise.\n */\nexport const chainAndCopyPromiseLike = <V, T extends PromiseLike<V>>(\n original: T,\n onSuccess: (value: V) => void,\n onError: (e: unknown) => void,\n): T => {\n const chained = original.then(\n value => {\n onSuccess(value);\n return value;\n },\n err => {\n onError(err);\n throw err;\n },\n ) as T;\n\n // if we're just dealing with \"normal\" Promise objects, return the chain\n return isActualPromise(chained) && isActualPromise(original) ? chained : copyProps(original, chained);\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst copyProps = <T extends Record<string, any>>(original: T, chained: T): T => {\n let mutated = false;\n //oxlint-disable-next-line guard-for-in\n for (const key in original) {\n if (key in chained) continue;\n mutated = true;\n const value = original[key];\n if (typeof value === 'function') {\n Object.defineProperty(chained, key, {\n value: (...args: unknown[]) => value.apply(original, args),\n enumerable: true,\n configurable: true,\n writable: true,\n });\n } else {\n (chained as Record<string, unknown>)[key] = value;\n }\n }\n\n if (mutated) Object.assign(chained, { [kChainedCopy]: true });\n return chained;\n};\n"],"names":[],"mappings":";;AAAA,MAAM,eAAA,GAAkB,CAAC,CAAC;AAC1B,EAAE,CAAA,YAAa,OAAA,IAAW,CAAC,CAAC,CAAA,GAA6C,YAAY,CAAC;;AAKtF,MAAM,YAAA,GAAe,MAAM,CAAC,qBAAqB,CAAC;;AAElD;AACA;AACA;AACA;AACO,MAAM,0BAA0B;AACvC,EAAE,QAAQ;AACV,EAAE,SAAS;AACX,EAAE,OAAO;AACT,KAAQ;AACR,EAAE,MAAM,OAAA,GAAU,QAAQ,CAAC,IAAI;AAC/B,IAAI,SAAS;AACb,MAAM,SAAS,CAAC,KAAK,CAAC;AACtB,MAAM,OAAO,KAAK;AAClB,IAAI,CAAC;AACL,IAAI,OAAO;AACX,MAAM,OAAO,CAAC,GAAG,CAAC;AAClB,MAAM,MAAM,GAAG;AACf,IAAI,CAAC;AACL,GAAE;;AAEF;AACA,EAAE,OAAO,eAAe,CAAC,OAAO,CAAA,IAAK,eAAe,CAAC,QAAQ,CAAA,GAAI,UAAU,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC;AACvG;;AAEA;AACA,MAAM,YAAY,CAAgC,QAAQ,EAAK,OAAO,KAAW;AACjF,EAAE,IAAI,OAAA,GAAU,KAAK;AACrB;AACA,EAAE,KAAK,MAAM,GAAA,IAAO,QAAQ,EAAE;AAC9B,IAAI,IAAI,GAAA,IAAO,OAAO,EAAE;AACxB,IAAI,OAAA,GAAU,IAAI;AAClB,IAAI,MAAM,KAAA,GAAQ,QAAQ,CAAC,GAAG,CAAC;AAC/B,IAAI,IAAI,OAAO,KAAA,KAAU,UAAU,EAAE;AACrC,MAAM,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE;AAC1C,QAAQ,KAAK,EAAE,CAAC,GAAG,IAAI,KAAgB,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC;AAClE,QAAQ,UAAU,EAAE,IAAI;AACxB,QAAQ,YAAY,EAAE,IAAI;AAC1B,QAAQ,QAAQ,EAAE,IAAI;AACtB,OAAO,CAAC;AACR,IAAI,OAAO;AACX,MAAM,CAAC,OAAA,GAAoC,GAAG,CAAA,GAAI,KAAK;AACvD,IAAI;AACJ,EAAE;;AAEF,EAAE,IAAI,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,GAAG,IAAA,EAAM,CAAC;AAC/D,EAAE,OAAO,OAAO;AAChB,CAAC;;;;"}
|
|
1
|
+
{"version":3,"file":"chain-and-copy-promiselike.js","sources":["../../../src/utils/chain-and-copy-promiselike.ts"],"sourcesContent":["const isActualPromise = (p: unknown) =>\n p instanceof Promise && !(p as unknown as ChainedPromiseLike<unknown>)[kChainedCopy];\n\ntype ChainedPromiseLike<T> = PromiseLike<T> & {\n [kChainedCopy]: true;\n};\nconst kChainedCopy = Symbol('chained PromiseLike');\n\n/**\n * Copy the properties from a decorated promiselike object onto its chained\n * actual promise.\n */\nexport const chainAndCopyPromiseLike = <V, T extends PromiseLike<V>>(\n original: T,\n onSuccess: (value: V) => void,\n onError: (e: unknown) => void,\n): T => {\n const chained = original.then(\n value => {\n onSuccess(value);\n return value;\n },\n err => {\n onError(err);\n throw err;\n },\n ) as T;\n\n // if we're just dealing with \"normal\" Promise objects, return the chain\n return isActualPromise(chained) && isActualPromise(original) ? chained : copyProps(original, chained);\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst copyProps = <T extends Record<string, any>>(original: T, chained: T): T => {\n if (!chained) return original;\n let mutated = false;\n //oxlint-disable-next-line guard-for-in\n for (const key in original) {\n if (key in chained) continue;\n mutated = true;\n const value = original[key];\n if (typeof value === 'function') {\n Object.defineProperty(chained, key, {\n value: (...args: unknown[]) => value.apply(original, args),\n enumerable: true,\n configurable: true,\n writable: true,\n });\n } else {\n (chained as Record<string, unknown>)[key] = value;\n }\n }\n\n if (mutated) Object.assign(chained, { [kChainedCopy]: true });\n return chained;\n};\n"],"names":[],"mappings":";;AAAA,MAAM,eAAA,GAAkB,CAAC,CAAC;AAC1B,EAAE,CAAA,YAAa,OAAA,IAAW,CAAC,CAAC,CAAA,GAA6C,YAAY,CAAC;;AAKtF,MAAM,YAAA,GAAe,MAAM,CAAC,qBAAqB,CAAC;;AAElD;AACA;AACA;AACA;AACO,MAAM,0BAA0B;AACvC,EAAE,QAAQ;AACV,EAAE,SAAS;AACX,EAAE,OAAO;AACT,KAAQ;AACR,EAAE,MAAM,OAAA,GAAU,QAAQ,CAAC,IAAI;AAC/B,IAAI,SAAS;AACb,MAAM,SAAS,CAAC,KAAK,CAAC;AACtB,MAAM,OAAO,KAAK;AAClB,IAAI,CAAC;AACL,IAAI,OAAO;AACX,MAAM,OAAO,CAAC,GAAG,CAAC;AAClB,MAAM,MAAM,GAAG;AACf,IAAI,CAAC;AACL,GAAE;;AAEF;AACA,EAAE,OAAO,eAAe,CAAC,OAAO,CAAA,IAAK,eAAe,CAAC,QAAQ,CAAA,GAAI,UAAU,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC;AACvG;;AAEA;AACA,MAAM,YAAY,CAAgC,QAAQ,EAAK,OAAO,KAAW;AACjF,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,QAAQ;AAC/B,EAAE,IAAI,OAAA,GAAU,KAAK;AACrB;AACA,EAAE,KAAK,MAAM,GAAA,IAAO,QAAQ,EAAE;AAC9B,IAAI,IAAI,GAAA,IAAO,OAAO,EAAE;AACxB,IAAI,OAAA,GAAU,IAAI;AAClB,IAAI,MAAM,KAAA,GAAQ,QAAQ,CAAC,GAAG,CAAC;AAC/B,IAAI,IAAI,OAAO,KAAA,KAAU,UAAU,EAAE;AACrC,MAAM,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE;AAC1C,QAAQ,KAAK,EAAE,CAAC,GAAG,IAAI,KAAgB,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC;AAClE,QAAQ,UAAU,EAAE,IAAI;AACxB,QAAQ,YAAY,EAAE,IAAI;AAC1B,QAAQ,QAAQ,EAAE,IAAI;AACtB,OAAO,CAAC;AACR,IAAI,OAAO;AACX,MAAM,CAAC,OAAA,GAAoC,GAAG,CAAA,GAAI,KAAK;AACvD,IAAI;AACJ,EAAE;;AAEF,EAAE,IAAI,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,GAAG,IAAA,EAAM,CAAC;AAC/D,EAAE,OAAO,OAAO;AAChB,CAAC;;;;"}
|
|
@@ -10,11 +10,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
10
10
|
* @returns void
|
|
11
11
|
*/
|
|
12
12
|
function replaceExports(
|
|
13
|
-
exports
|
|
13
|
+
exports,
|
|
14
14
|
exportName,
|
|
15
15
|
wrappedConstructor,
|
|
16
16
|
) {
|
|
17
|
-
const original = exports
|
|
17
|
+
const original = exports[exportName];
|
|
18
18
|
|
|
19
19
|
if (typeof original !== 'function') {
|
|
20
20
|
return;
|
|
@@ -22,10 +22,10 @@ function replaceExports(
|
|
|
22
22
|
|
|
23
23
|
// Replace the named export - handle read-only properties
|
|
24
24
|
try {
|
|
25
|
-
exports
|
|
25
|
+
exports[exportName] = wrappedConstructor;
|
|
26
26
|
} catch {
|
|
27
27
|
// If direct assignment fails, override the property descriptor
|
|
28
|
-
Object.defineProperty(exports
|
|
28
|
+
Object.defineProperty(exports, exportName, {
|
|
29
29
|
value: wrappedConstructor,
|
|
30
30
|
writable: true,
|
|
31
31
|
configurable: true,
|
|
@@ -34,11 +34,11 @@ function replaceExports(
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// Replace the default export if it points to the original constructor
|
|
37
|
-
if (exports
|
|
37
|
+
if (exports.default === original) {
|
|
38
38
|
try {
|
|
39
|
-
exports
|
|
39
|
+
exports.default = wrappedConstructor;
|
|
40
40
|
} catch {
|
|
41
|
-
Object.defineProperty(exports
|
|
41
|
+
Object.defineProperty(exports, 'default', {
|
|
42
42
|
value: wrappedConstructor,
|
|
43
43
|
writable: true,
|
|
44
44
|
configurable: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exports.js","sources":["../../../src/utils/exports.ts"],"sourcesContent":["/**\n * Replaces constructor functions in module exports, handling read-only properties,\n * and both default and named exports by wrapping them with the constructor.\n *\n * @param exports The module exports object to modify\n * @param exportName The name of the export to replace (e.g., 'GoogleGenAI', 'Anthropic', 'OpenAI')\n * @param wrappedConstructor The wrapped constructor function to replace the original with\n * @returns void\n */\nexport function replaceExports(\n exports: { [key: string]: unknown },\n exportName: string,\n wrappedConstructor: unknown,\n): void {\n const original = exports[exportName];\n\n if (typeof original !== 'function') {\n return;\n }\n\n // Replace the named export - handle read-only properties\n try {\n exports[exportName] = wrappedConstructor;\n } catch {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, exportName, {\n value: wrappedConstructor,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Replace the default export if it points to the original constructor\n if (exports.default === original) {\n try {\n exports.default = wrappedConstructor;\n } catch {\n Object.defineProperty(exports, 'default', {\n value: wrappedConstructor,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n}\n"],"names":[
|
|
1
|
+
{"version":3,"file":"exports.js","sources":["../../../src/utils/exports.ts"],"sourcesContent":["/**\n * Replaces constructor functions in module exports, handling read-only properties,\n * and both default and named exports by wrapping them with the constructor.\n *\n * @param exports The module exports object to modify\n * @param exportName The name of the export to replace (e.g., 'GoogleGenAI', 'Anthropic', 'OpenAI')\n * @param wrappedConstructor The wrapped constructor function to replace the original with\n * @returns void\n */\nexport function replaceExports(\n exports: { [key: string]: unknown },\n exportName: string,\n wrappedConstructor: unknown,\n): void {\n const original = exports[exportName];\n\n if (typeof original !== 'function') {\n return;\n }\n\n // Replace the named export - handle read-only properties\n try {\n exports[exportName] = wrappedConstructor;\n } catch {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, exportName, {\n value: wrappedConstructor,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Replace the default export if it points to the original constructor\n if (exports.default === original) {\n try {\n exports.default = wrappedConstructor;\n } catch {\n Object.defineProperty(exports, 'default', {\n value: wrappedConstructor,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n}\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,cAAc;AAC9B,EAAE,OAAO;AACT,EAAE,UAAU;AACZ,EAAE,kBAAkB;AACpB,EAAQ;AACR,EAAE,MAAM,QAAA,GAAW,OAAO,CAAC,UAAU,CAAC;;AAEtC,EAAE,IAAI,OAAO,QAAA,KAAa,UAAU,EAAE;AACtC,IAAI;AACJ,EAAE;;AAEF;AACA,EAAE,IAAI;AACN,IAAI,OAAO,CAAC,UAAU,CAAA,GAAI,kBAAkB;AAC5C,EAAE,EAAE,MAAM;AACV;AACA,IAAI,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE;AAC/C,MAAM,KAAK,EAAE,kBAAkB;AAC/B,MAAM,QAAQ,EAAE,IAAI;AACpB,MAAM,YAAY,EAAE,IAAI;AACxB,MAAM,UAAU,EAAE,IAAI;AACtB,KAAK,CAAC;AACN,EAAE;;AAEF;AACA,EAAE,IAAI,OAAO,CAAC,OAAA,KAAY,QAAQ,EAAE;AACpC,IAAI,IAAI;AACR,MAAM,OAAO,CAAC,OAAA,GAAU,kBAAkB;AAC1C,IAAI,EAAE,MAAM;AACZ,MAAM,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,SAAS,EAAE;AAChD,QAAQ,KAAK,EAAE,kBAAkB;AACjC,QAAQ,QAAQ,EAAE,IAAI;AACtB,QAAQ,YAAY,EAAE,IAAI;AAC1B,QAAQ,UAAU,EAAE,IAAI;AACxB,OAAO,CAAC;AACR,IAAI;AACJ,EAAE;AACF;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const exports$1 = require('../exports.js');
|
|
4
4
|
const debugLogger = require('./debug-logger.js');
|
|
5
5
|
const vercelWaitUntil = require('./vercelWaitUntil.js');
|
|
6
6
|
const worldwide = require('./worldwide.js');
|
|
@@ -8,7 +8,7 @@ const worldwide = require('./worldwide.js');
|
|
|
8
8
|
async function flushWithTimeout(timeout) {
|
|
9
9
|
try {
|
|
10
10
|
debugLogger.debug.log('Flushing events...');
|
|
11
|
-
await
|
|
11
|
+
await exports$1.flush(timeout);
|
|
12
12
|
debugLogger.debug.log('Done flushing events');
|
|
13
13
|
} catch (e) {
|
|
14
14
|
debugLogger.debug.log('Error while flushing events:\n', e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flushIfServerless.js","sources":["../../../src/utils/flushIfServerless.ts"],"sourcesContent":["import { flush } from '../exports';\nimport { debug } from './debug-logger';\nimport { vercelWaitUntil } from './vercelWaitUntil';\nimport { GLOBAL_OBJ } from './worldwide';\n\ntype MinimalCloudflareContext = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n waitUntil(promise: Promise<any>): void;\n};\n\nasync function flushWithTimeout(timeout: number): Promise<void> {\n try {\n debug.log('Flushing events...');\n await flush(timeout);\n debug.log('Done flushing events');\n } catch (e) {\n debug.log('Error while flushing events:\\n', e);\n }\n}\n\n/**\n * Flushes the event queue with a timeout in serverless environments to ensure that events are sent to Sentry before the\n * serverless function execution ends.\n *\n * The function is async, but in environments that support a `waitUntil` mechanism, it will run synchronously.\n *\n * This function is aware of the following serverless platforms:\n * - Cloudflare: If a Cloudflare context is provided, it will use `ctx.waitUntil()` to flush events (keeps the `this` context of `ctx`).\n * If a `cloudflareWaitUntil` function is provided, it will use that to flush events (looses the `this` context of `ctx`).\n * - Vercel: It detects the Vercel environment and uses Vercel's `waitUntil` function.\n * - Other Serverless (AWS Lambda, Google Cloud, etc.): It detects the environment via environment variables\n * and uses a regular `await flush()`.\n *\n * @internal This function is supposed for internal Sentry SDK usage only.\n * @hidden\n */\nexport async function flushIfServerless(\n params: // eslint-disable-next-line @typescript-eslint/no-explicit-any\n | { timeout?: number; cloudflareWaitUntil?: (task: Promise<any>) => void }\n | { timeout?: number; cloudflareCtx?: MinimalCloudflareContext } = {},\n): Promise<void> {\n const { timeout = 2000 } = params;\n\n if ('cloudflareWaitUntil' in params && typeof params?.cloudflareWaitUntil === 'function') {\n params.cloudflareWaitUntil(flushWithTimeout(timeout));\n return;\n }\n\n if ('cloudflareCtx' in params && typeof params.cloudflareCtx?.waitUntil === 'function') {\n params.cloudflareCtx.waitUntil(flushWithTimeout(timeout));\n return;\n }\n\n // Note: vercelWaitUntil only does something in Vercel Edge runtime\n // In Node runtime, we use process.on('SIGTERM') instead\n // @ts-expect-error This is not typed\n if (GLOBAL_OBJ[Symbol.for('@vercel/request-context')]) {\n // Vercel has a waitUntil equivalent that works without execution context\n vercelWaitUntil(flushWithTimeout(timeout));\n return;\n }\n\n if (typeof process === 'undefined') {\n return;\n }\n\n const isServerless =\n !!process.env.FUNCTIONS_WORKER_RUNTIME || // Azure Functions\n !!process.env.LAMBDA_TASK_ROOT || // AWS Lambda\n !!process.env.K_SERVICE || // Google Cloud Run\n !!process.env.CF_PAGES || // Cloudflare Pages\n !!process.env.VERCEL ||\n !!process.env.NETLIFY;\n\n if (isServerless) {\n // Use regular flush for environments without a generic waitUntil mechanism\n await flushWithTimeout(timeout);\n }\n}\n"],"names":["debug","flush","GLOBAL_OBJ","vercelWaitUntil"],"mappings":";;;;;;;AAUA,eAAe,gBAAgB,CAAC,OAAO,EAAyB;AAChE,EAAE,IAAI;AACN,IAAIA,iBAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC;AACnC,IAAI,MAAMC,
|
|
1
|
+
{"version":3,"file":"flushIfServerless.js","sources":["../../../src/utils/flushIfServerless.ts"],"sourcesContent":["import { flush } from '../exports';\nimport { debug } from './debug-logger';\nimport { vercelWaitUntil } from './vercelWaitUntil';\nimport { GLOBAL_OBJ } from './worldwide';\n\ntype MinimalCloudflareContext = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n waitUntil(promise: Promise<any>): void;\n};\n\nasync function flushWithTimeout(timeout: number): Promise<void> {\n try {\n debug.log('Flushing events...');\n await flush(timeout);\n debug.log('Done flushing events');\n } catch (e) {\n debug.log('Error while flushing events:\\n', e);\n }\n}\n\n/**\n * Flushes the event queue with a timeout in serverless environments to ensure that events are sent to Sentry before the\n * serverless function execution ends.\n *\n * The function is async, but in environments that support a `waitUntil` mechanism, it will run synchronously.\n *\n * This function is aware of the following serverless platforms:\n * - Cloudflare: If a Cloudflare context is provided, it will use `ctx.waitUntil()` to flush events (keeps the `this` context of `ctx`).\n * If a `cloudflareWaitUntil` function is provided, it will use that to flush events (looses the `this` context of `ctx`).\n * - Vercel: It detects the Vercel environment and uses Vercel's `waitUntil` function.\n * - Other Serverless (AWS Lambda, Google Cloud, etc.): It detects the environment via environment variables\n * and uses a regular `await flush()`.\n *\n * @internal This function is supposed for internal Sentry SDK usage only.\n * @hidden\n */\nexport async function flushIfServerless(\n params: // eslint-disable-next-line @typescript-eslint/no-explicit-any\n | { timeout?: number; cloudflareWaitUntil?: (task: Promise<any>) => void }\n | { timeout?: number; cloudflareCtx?: MinimalCloudflareContext } = {},\n): Promise<void> {\n const { timeout = 2000 } = params;\n\n if ('cloudflareWaitUntil' in params && typeof params?.cloudflareWaitUntil === 'function') {\n params.cloudflareWaitUntil(flushWithTimeout(timeout));\n return;\n }\n\n if ('cloudflareCtx' in params && typeof params.cloudflareCtx?.waitUntil === 'function') {\n params.cloudflareCtx.waitUntil(flushWithTimeout(timeout));\n return;\n }\n\n // Note: vercelWaitUntil only does something in Vercel Edge runtime\n // In Node runtime, we use process.on('SIGTERM') instead\n // @ts-expect-error This is not typed\n if (GLOBAL_OBJ[Symbol.for('@vercel/request-context')]) {\n // Vercel has a waitUntil equivalent that works without execution context\n vercelWaitUntil(flushWithTimeout(timeout));\n return;\n }\n\n if (typeof process === 'undefined') {\n return;\n }\n\n const isServerless =\n !!process.env.FUNCTIONS_WORKER_RUNTIME || // Azure Functions\n !!process.env.LAMBDA_TASK_ROOT || // AWS Lambda\n !!process.env.K_SERVICE || // Google Cloud Run\n !!process.env.CF_PAGES || // Cloudflare Pages\n !!process.env.VERCEL ||\n !!process.env.NETLIFY;\n\n if (isServerless) {\n // Use regular flush for environments without a generic waitUntil mechanism\n await flushWithTimeout(timeout);\n }\n}\n"],"names":["debug","flush","GLOBAL_OBJ","vercelWaitUntil"],"mappings":";;;;;;;AAUA,eAAe,gBAAgB,CAAC,OAAO,EAAyB;AAChE,EAAE,IAAI;AACN,IAAIA,iBAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC;AACnC,IAAI,MAAMC,eAAK,CAAC,OAAO,CAAC;AACxB,IAAID,iBAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC;AACrC,EAAE,CAAA,CAAE,OAAO,CAAC,EAAE;AACd,IAAIA,iBAAK,CAAC,GAAG,CAAC,gCAAgC,EAAE,CAAC,CAAC;AAClD,EAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,iBAAiB;AACvC,EAAE;;AAEE,GAAmE,EAAE;AACzE,EAAiB;AACjB,EAAE,MAAM,EAAE,OAAA,GAAU,IAAA,EAAK,GAAI,MAAM;;AAEnC,EAAE,IAAI,qBAAA,IAAyB,MAAA,IAAU,OAAO,MAAM,EAAE,mBAAA,KAAwB,UAAU,EAAE;AAC5F,IAAI,MAAM,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;AACzD,IAAI;AACJ,EAAE;;AAEF,EAAE,IAAI,eAAA,IAAmB,UAAU,OAAO,MAAM,CAAC,aAAa,EAAE,SAAA,KAAc,UAAU,EAAE;AAC1F,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC7D,IAAI;AACJ,EAAE;;AAEF;AACA;AACA;AACA,EAAE,IAAIE,oBAAU,CAAC,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,EAAE;AACzD;AACA,IAAIC,+BAAe,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC9C,IAAI;AACJ,EAAE;;AAEF,EAAE,IAAI,OAAO,OAAA,KAAY,WAAW,EAAE;AACtC,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,YAAA;AACR,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAA;AAClB,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAA;AAClB,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,SAAA;AAClB,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAA;AAClB,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAA;AAClB,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO;;AAEzB,EAAE,IAAI,YAAY,EAAE;AACpB;AACA,IAAI,MAAM,gBAAgB,CAAC,OAAO,CAAC;AACnC,EAAE;AACF;;;;"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Often we patch a module's default export, but we want to be able to do
|
|
5
|
+
* something like this:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* patchTheThing(await import('the-thing'));
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* Or like this:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* import theThing from 'the-thing';
|
|
15
|
+
* patchTheThing(theThing);
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Note: this does not support modules with a falsey default export. However,
|
|
19
|
+
* presumably in those cases, there's no default export to patch anyway.
|
|
20
|
+
*/
|
|
21
|
+
function getDefaultExport(moduleExport) {
|
|
22
|
+
return (
|
|
23
|
+
(!!moduleExport &&
|
|
24
|
+
typeof moduleExport === 'object' &&
|
|
25
|
+
'default' in moduleExport &&
|
|
26
|
+
(moduleExport ).default) ||
|
|
27
|
+
(moduleExport )
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
exports.getDefaultExport = getDefaultExport;
|
|
32
|
+
//# sourceMappingURL=get-default-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-default-export.js","sources":["../../../src/utils/get-default-export.ts"],"sourcesContent":["/**\n * Often we patch a module's default export, but we want to be able to do\n * something like this:\n *\n * ```ts\n * patchTheThing(await import('the-thing'));\n * ```\n *\n * Or like this:\n *\n * ```ts\n * import theThing from 'the-thing';\n * patchTheThing(theThing);\n * ```\n *\n * Note: this does not support modules with a falsey default export. However,\n * presumably in those cases, there's no default export to patch anyway.\n */\nexport function getDefaultExport<T>(moduleExport: T | { default: T }): T {\n return (\n (!!moduleExport &&\n typeof moduleExport === 'object' &&\n 'default' in moduleExport &&\n (moduleExport as { default: T }).default) ||\n (moduleExport as T)\n );\n}\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAI,YAAY,EAAyB;AACzE,EAAE;AACF,IAAI,CAAC,CAAC,CAAC,YAAA;AACP,MAAM,OAAO,YAAA,KAAiB,QAAA;AAC9B,MAAM,SAAA,IAAa,YAAA;AACnB,MAAM,CAAC,YAAA,GAAgC,OAAO;AAC9C,KAAK,YAAA;AACL;AACA;;;;"}
|
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
+
const debugBuild = require('../debug-build.js');
|
|
4
|
+
const debugLogger = require('./debug-logger.js');
|
|
5
|
+
const timer = require('./timer.js');
|
|
6
|
+
|
|
7
|
+
/* eslint-disable max-lines-per-function */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Maximum size of incoming HTTP request bodies attached to events.
|
|
11
|
+
*
|
|
12
|
+
* - `'none'`: No request bodies will be attached
|
|
13
|
+
* - `'small'`: Request bodies up to 1,000 bytes will be attached
|
|
14
|
+
* - `'medium'`: Request bodies up to 10,000 bytes will be attached
|
|
15
|
+
* - `'always'`: Request bodies will always be attached (up to 1MB hard cap)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** Hard cap on captured body size, even when `maxRequestBodySize` is `'always'`. */
|
|
19
|
+
const MAX_BODY_BYTE_LENGTH = 1024 * 1024;
|
|
20
|
+
|
|
21
|
+
/** Content types that are safe to capture as text. */
|
|
22
|
+
const TEXT_CONTENT_TYPES = [
|
|
23
|
+
'text/',
|
|
24
|
+
'application/json',
|
|
25
|
+
'application/x-www-form-urlencoded',
|
|
26
|
+
'application/xml',
|
|
27
|
+
'application/graphql',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Convert a `maxRequestBodySize` setting to a maximum byte length.
|
|
32
|
+
*/
|
|
33
|
+
function getMaxBodyByteLength(maxRequestBodySize) {
|
|
34
|
+
if (maxRequestBodySize === 'small') return 1000;
|
|
35
|
+
if (maxRequestBodySize === 'medium') return 10000;
|
|
36
|
+
return MAX_BODY_BYTE_LENGTH;
|
|
37
|
+
}
|
|
38
|
+
|
|
3
39
|
/**
|
|
4
40
|
* Transforms a `Headers` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into a simple key-value dict.
|
|
5
41
|
* The header keys will be lower case: e.g. A "Content-Type" header will be stored as "content-type".
|
|
@@ -54,6 +90,96 @@ function winterCGRequestToRequestData(req) {
|
|
|
54
90
|
};
|
|
55
91
|
}
|
|
56
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Checks if the content type is textual and safe to capture.
|
|
95
|
+
*/
|
|
96
|
+
function isTextualContentType(contentType) {
|
|
97
|
+
if (!contentType) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
const lowerContentType = contentType.toLowerCase();
|
|
101
|
+
return TEXT_CONTENT_TYPES.some(type => lowerContentType.includes(type));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Captures the body from a Web Fetch API Request and adds it to the isolation scope.
|
|
106
|
+
*
|
|
107
|
+
* This function clones the request to read the body without affecting the original.
|
|
108
|
+
* Only textual content types are captured - binary data is skipped.
|
|
109
|
+
*
|
|
110
|
+
* This is used by WinterCG-compatible runtimes (Cloudflare Workers, Deno, Bun, Vercel Edge, etc.)
|
|
111
|
+
* that use the Web Fetch API Request object.
|
|
112
|
+
*
|
|
113
|
+
* @param request - The incoming Web Fetch API Request
|
|
114
|
+
* @param isolationScope - The isolation scope to add the body to
|
|
115
|
+
* @param maxRequestBodySize - The maximum size of the request body to capture ('small' = 1KB, 'medium' = 10KB, 'always' = 1MB)
|
|
116
|
+
*/
|
|
117
|
+
async function captureBodyFromWinterCGRequest(
|
|
118
|
+
request,
|
|
119
|
+
isolationScope,
|
|
120
|
+
maxRequestBodySize,
|
|
121
|
+
) {
|
|
122
|
+
try {
|
|
123
|
+
const contentType = request.headers.get('content-type');
|
|
124
|
+
|
|
125
|
+
if (!isTextualContentType(contentType)) {
|
|
126
|
+
debugBuild.DEBUG_BUILD && debugLogger.debug.log('Skipping body capture for non-textual content type:', contentType);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (!request.body) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const contentLength = request.headers.get('content-length');
|
|
135
|
+
const maxBodySize = getMaxBodyByteLength(maxRequestBodySize);
|
|
136
|
+
|
|
137
|
+
if (contentLength) {
|
|
138
|
+
const length = parseInt(contentLength, 10);
|
|
139
|
+
if (!isNaN(length) && length > MAX_BODY_BYTE_LENGTH) {
|
|
140
|
+
debugBuild.DEBUG_BUILD && debugLogger.debug.log('Skipping body capture: body too large', length);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const clonedRequest = request.clone();
|
|
146
|
+
const bodyPromise = clonedRequest.text();
|
|
147
|
+
const timeoutPromise = new Promise(resolve => {
|
|
148
|
+
timer.safeUnref(setTimeout(() => resolve(null), 2000));
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const body = await Promise.race([bodyPromise, timeoutPromise]);
|
|
152
|
+
|
|
153
|
+
if (body === null) {
|
|
154
|
+
debugBuild.DEBUG_BUILD && debugLogger.debug.log('Timeout reading request body');
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!body) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Using TextEncoder to get byte length for UTF-8 strings
|
|
163
|
+
const encoder = new TextEncoder();
|
|
164
|
+
const bytes = encoder.encode(body);
|
|
165
|
+
const bodyByteLength = bytes.length;
|
|
166
|
+
|
|
167
|
+
let truncatedBody;
|
|
168
|
+
if (bodyByteLength > maxBodySize) {
|
|
169
|
+
const decoder = new TextDecoder();
|
|
170
|
+
truncatedBody = `${decoder.decode(bytes.slice(0, maxBodySize - 3))}...`;
|
|
171
|
+
} else {
|
|
172
|
+
truncatedBody = body;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
isolationScope.setSDKProcessingMetadata({ normalizedRequest: { data: truncatedBody } });
|
|
176
|
+
|
|
177
|
+
debugBuild.DEBUG_BUILD && debugLogger.debug.log('Captured request body:', bodyByteLength, 'bytes');
|
|
178
|
+
} catch (error) {
|
|
179
|
+
debugBuild.DEBUG_BUILD && debugLogger.debug.error('Error capturing request body:', error);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
57
183
|
/**
|
|
58
184
|
* Convert a HTTP request object to RequestEventData to be passed as normalizedRequest.
|
|
59
185
|
* Instead of allowing `PolymorphicRequest` to be passed,
|
|
@@ -312,7 +438,10 @@ function extractQueryParamsFromUrl(url) {
|
|
|
312
438
|
}
|
|
313
439
|
}
|
|
314
440
|
|
|
441
|
+
exports.MAX_BODY_BYTE_LENGTH = MAX_BODY_BYTE_LENGTH;
|
|
442
|
+
exports.captureBodyFromWinterCGRequest = captureBodyFromWinterCGRequest;
|
|
315
443
|
exports.extractQueryParamsFromUrl = extractQueryParamsFromUrl;
|
|
444
|
+
exports.getMaxBodyByteLength = getMaxBodyByteLength;
|
|
316
445
|
exports.headersToDict = headersToDict;
|
|
317
446
|
exports.httpHeadersToSpanAttributes = httpHeadersToSpanAttributes;
|
|
318
447
|
exports.httpRequestToRequestData = httpRequestToRequestData;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sources":["../../../src/utils/request.ts"],"sourcesContent":["import type { PolymorphicRequest } from '../types-hoist/polymorphics';\nimport type { RequestEventData } from '../types-hoist/request';\nimport type { WebFetchHeaders, WebFetchRequest } from '../types-hoist/webfetchapi';\n\n/**\n * Transforms a `Headers` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into a simple key-value dict.\n * The header keys will be lower case: e.g. A \"Content-Type\" header will be stored as \"content-type\".\n */\nexport function winterCGHeadersToDict(winterCGHeaders: WebFetchHeaders): Record<string, string> {\n const headers: Record<string, string> = {};\n try {\n winterCGHeaders.forEach((value, key) => {\n if (typeof value === 'string') {\n // We check that value is a string even though it might be redundant to make sure prototype pollution is not possible.\n headers[key] = value;\n }\n });\n } catch {\n // just return the empty headers\n }\n\n return headers;\n}\n\n/**\n * Convert common request headers to a simple dictionary.\n */\nexport function headersToDict(reqHeaders: Record<string, string | string[] | undefined>): Record<string, string> {\n const headers: Record<string, string> = Object.create(null);\n\n try {\n Object.entries(reqHeaders).forEach(([key, value]) => {\n if (typeof value === 'string') {\n headers[key] = value;\n }\n });\n } catch {\n // just return the empty headers\n }\n\n return headers;\n}\n\n/**\n * Converts a `Request` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into the format that the `RequestData` integration understands.\n */\nexport function winterCGRequestToRequestData(req: WebFetchRequest): RequestEventData {\n const headers = winterCGHeadersToDict(req.headers);\n\n return {\n method: req.method,\n url: req.url,\n query_string: extractQueryParamsFromUrl(req.url),\n headers,\n // TODO: Can we extract body data from the request?\n };\n}\n\n/**\n * Convert a HTTP request object to RequestEventData to be passed as normalizedRequest.\n * Instead of allowing `PolymorphicRequest` to be passed,\n * we want to be more specific and generally require a http.IncomingMessage-like object.\n */\nexport function httpRequestToRequestData(request: {\n method?: string;\n url?: string;\n headers?: {\n [key: string]: string | string[] | undefined;\n };\n protocol?: string;\n socket?: {\n encrypted?: boolean;\n remoteAddress?: string;\n };\n}): RequestEventData {\n const headers = request.headers || {};\n\n // Check for x-forwarded-host first, then fall back to host header\n const forwardedHost = typeof headers['x-forwarded-host'] === 'string' ? headers['x-forwarded-host'] : undefined;\n const host = forwardedHost || (typeof headers.host === 'string' ? headers.host : undefined);\n\n // Check for x-forwarded-proto first, then fall back to existing protocol detection\n const forwardedProto = typeof headers['x-forwarded-proto'] === 'string' ? headers['x-forwarded-proto'] : undefined;\n const protocol = forwardedProto || request.protocol || (request.socket?.encrypted ? 'https' : 'http');\n\n const url = request.url || '';\n\n const absoluteUrl = getAbsoluteUrl({\n url,\n host,\n protocol,\n });\n\n // This is non-standard, but may be sometimes set\n // It may be overwritten later by our own body handling\n const data = (request as PolymorphicRequest).body || undefined;\n\n // This is non-standard, but may be set on e.g. Next.js or Express requests\n const cookies = (request as PolymorphicRequest).cookies;\n\n return {\n url: absoluteUrl,\n method: request.method,\n query_string: extractQueryParamsFromUrl(url),\n headers: headersToDict(headers),\n cookies,\n data,\n };\n}\n\nfunction getAbsoluteUrl({\n url,\n protocol,\n host,\n}: {\n url?: string;\n protocol: string;\n host?: string;\n}): string | undefined {\n if (url?.startsWith('http')) {\n return url;\n }\n\n if (url && host) {\n return `${protocol}://${host}${url}`;\n }\n\n return undefined;\n}\n\nconst SENSITIVE_HEADER_SNIPPETS = [\n 'auth',\n 'token',\n 'secret',\n 'session', // for the user_session cookie\n 'password',\n 'passwd',\n 'pwd',\n 'key',\n 'jwt',\n 'bearer',\n 'sso',\n 'saml',\n 'csrf',\n 'xsrf',\n 'credentials',\n // Always treat cookie headers as sensitive in case individual key-value cookie pairs cannot properly be extracted\n 'set-cookie',\n 'cookie',\n];\n\n/**\n * Extra substrings matched only against individual Cookie / Set-Cookie **names** (not header names),\n * so we can cover common session secrets that do not match {@link SENSITIVE_HEADER_SNIPPETS}\n * (e.g. `connect.sid` does not contain `session`) without false positives on arbitrary HTTP headers.\n *\n * Cookie names are checked with the same `includes()` list as headers plus these entries; omit redundant\n * cookie-only snippets that are already implied by a header match (e.g. `oauth` → `auth`, `id_token` → `token`,\n * `next-auth` → `auth`).\n */\nconst SENSITIVE_COOKIE_NAME_SNIPPETS = [\n // Express / Connect default session cookie\n '.sid',\n // Opaque session ids (PHPSESSID, ASPSESSIONID*, BIGipServer*, *sessid*, …)\n 'sessid',\n // Laravel etc. \"remember me\" tokens\n 'remember',\n // OIDC / OAuth auxiliary (`oauth*` covered by header snippet `auth`)\n 'oidc',\n 'pkce',\n 'nonce',\n // RFC 6265bis high-security cookie name prefixes\n '__secure-',\n '__host-',\n // Load balancer / CDN sticky-session cookies (opaque routing tokens)\n 'awsalb',\n 'awselb',\n 'akamai',\n // BaaS / IdP session cookies (names often omit \"session\")\n '__stripe',\n 'cognito',\n 'firebase',\n 'supabase',\n 'sb-',\n // Step-up / MFA cookies\n 'mfa',\n '2fa',\n];\n\nconst PII_HEADER_SNIPPETS = ['x-forwarded-', '-user'];\n\n/**\n * Converts incoming HTTP request or response headers to OpenTelemetry span attributes following semantic conventions.\n * Header names are converted to the format: http.<request|response>.header.<key>\n * where <key> is the header name in lowercase with dashes converted to underscores.\n *\n * @param lifecycle - The lifecycle of the headers, either 'request' or 'response'\n *\n * @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/#http-request-header\n * @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/#http-response-header\n *\n * @see https://getsentry.github.io/sentry-conventions/attributes/http/#http-request-header-key\n * @see https://getsentry.github.io/sentry-conventions/attributes/http/#http-response-header-key\n */\nexport function httpHeadersToSpanAttributes(\n headers: Record<string, string | string[] | undefined>,\n sendDefaultPii: boolean = false,\n lifecycle: 'request' | 'response' = 'request',\n): Record<string, string> {\n const spanAttributes: Record<string, string> = {};\n\n try {\n Object.entries(headers).forEach(([key, value]) => {\n if (value == null) {\n return;\n }\n\n const lowerCasedHeaderKey = key.toLowerCase();\n const isCookieHeader = lowerCasedHeaderKey === 'cookie' || lowerCasedHeaderKey === 'set-cookie';\n\n if (isCookieHeader && typeof value === 'string' && value !== '') {\n // Set-Cookie: single cookie with attributes (\"name=value; HttpOnly; Secure\")\n // Cookie: multiple cookies separated by \"; \" (\"cookie1=value1; cookie2=value2\")\n const isSetCookie = lowerCasedHeaderKey === 'set-cookie';\n const semicolonIndex = value.indexOf(';');\n const cookieString = isSetCookie && semicolonIndex !== -1 ? value.substring(0, semicolonIndex) : value;\n const cookies = isSetCookie ? [cookieString] : cookieString.split('; ');\n\n for (const cookie of cookies) {\n // Split only at the first '=' to preserve '=' characters in cookie values\n const equalSignIndex = cookie.indexOf('=');\n const cookieKey = equalSignIndex !== -1 ? cookie.substring(0, equalSignIndex) : cookie;\n const cookieValue = equalSignIndex !== -1 ? cookie.substring(equalSignIndex + 1) : '';\n\n const lowerCasedCookieKey = cookieKey.toLowerCase();\n\n addSpanAttribute({\n spanAttributes,\n headerKey: lowerCasedHeaderKey,\n cookieKey: lowerCasedCookieKey,\n value: cookieValue,\n sendDefaultPii,\n lifecycle,\n });\n }\n } else {\n addSpanAttribute({\n spanAttributes,\n headerKey: lowerCasedHeaderKey,\n value,\n sendDefaultPii,\n lifecycle,\n });\n }\n });\n } catch {\n // Return empty object if there's an error\n }\n\n return spanAttributes;\n}\n\nfunction normalizeAttributeKey(key: string): string {\n return key.replace(/-/g, '_');\n}\n\ntype AddSpanAttributeOptions = {\n spanAttributes: Record<string, string>;\n /** Lowercased HTTP header name (e.g. `cookie`, `set-cookie`, `accept`). */\n headerKey: string;\n /**\n * Lowercased cookie name when this attribute comes from a parsed `Cookie` / `Set-Cookie` value.\n * Omit for non-cookie headers; when present and non-empty, cookie-specific sensitivity rules apply.\n */\n cookieKey?: string;\n value: string | string[] | undefined;\n sendDefaultPii: boolean;\n lifecycle: 'request' | 'response';\n};\n\nfunction addSpanAttribute({\n spanAttributes,\n headerKey,\n cookieKey,\n value,\n sendDefaultPii,\n lifecycle,\n}: AddSpanAttributeOptions): void {\n const isCookieSubKey = Boolean(cookieKey);\n const nameForSensitivity = cookieKey || headerKey;\n const headerValue = handleHttpHeader(nameForSensitivity, value, sendDefaultPii, isCookieSubKey);\n if (headerValue == null) {\n return;\n }\n\n const normalizedKey = `http.${lifecycle}.header.${normalizeAttributeKey(headerKey)}${cookieKey ? `.${normalizeAttributeKey(cookieKey)}` : ''}`;\n spanAttributes[normalizedKey] = headerValue;\n}\n\nfunction handleHttpHeader(\n lowerCasedKey: string,\n value: string | string[] | undefined,\n sendPii: boolean,\n isCookieSubKey: boolean = false,\n): string | undefined {\n const snippetsForSensitivity = isCookieSubKey\n ? [...SENSITIVE_HEADER_SNIPPETS, ...SENSITIVE_COOKIE_NAME_SNIPPETS]\n : SENSITIVE_HEADER_SNIPPETS;\n\n const isSensitive = sendPii\n ? snippetsForSensitivity.some(snippet => lowerCasedKey.includes(snippet))\n : [...PII_HEADER_SNIPPETS, ...snippetsForSensitivity].some(snippet => lowerCasedKey.includes(snippet));\n\n if (isSensitive) {\n return '[Filtered]';\n } else if (Array.isArray(value)) {\n return value.map(v => (v != null ? String(v) : v)).join(';');\n } else if (typeof value === 'string') {\n return value;\n }\n\n return undefined;\n}\n\n/** Extract the query params from an URL. */\nexport function extractQueryParamsFromUrl(url: string): string | undefined {\n // url is path and query string\n if (!url) {\n return;\n }\n\n try {\n // The `URL` constructor can't handle internal URLs of the form `/some/path/here`, so stick a dummy protocol and\n // hostname as the base. Since the point here is just to grab the query string, it doesn't matter what we use.\n const queryParams = new URL(url, 'http://s.io').search.slice(1);\n return queryParams.length ? queryParams : undefined;\n } catch {\n return undefined;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"request.js","sources":["../../../src/utils/request.ts"],"sourcesContent":["/* eslint-disable max-lines-per-function */\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { Scope } from '../scope';\nimport type { PolymorphicRequest } from '../types-hoist/polymorphics';\nimport type { RequestEventData } from '../types-hoist/request';\nimport type { WebFetchHeaders, WebFetchRequest } from '../types-hoist/webfetchapi';\nimport { debug } from './debug-logger';\nimport { safeUnref } from './timer';\n\n/**\n * Maximum size of incoming HTTP request bodies attached to events.\n *\n * - `'none'`: No request bodies will be attached\n * - `'small'`: Request bodies up to 1,000 bytes will be attached\n * - `'medium'`: Request bodies up to 10,000 bytes will be attached\n * - `'always'`: Request bodies will always be attached (up to 1MB hard cap)\n */\nexport type MaxRequestBodySize = 'none' | 'small' | 'medium' | 'always';\n\n/** Hard cap on captured body size, even when `maxRequestBodySize` is `'always'`. */\nexport const MAX_BODY_BYTE_LENGTH = 1_024 * 1_024;\n\n/** Content types that are safe to capture as text. */\nconst TEXT_CONTENT_TYPES = [\n 'text/',\n 'application/json',\n 'application/x-www-form-urlencoded',\n 'application/xml',\n 'application/graphql',\n];\n\n/**\n * Convert a `maxRequestBodySize` setting to a maximum byte length.\n */\nexport function getMaxBodyByteLength(maxRequestBodySize: Exclude<MaxRequestBodySize, 'none'>): number {\n if (maxRequestBodySize === 'small') return 1_000;\n if (maxRequestBodySize === 'medium') return 10_000;\n return MAX_BODY_BYTE_LENGTH;\n}\n\n/**\n * Transforms a `Headers` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into a simple key-value dict.\n * The header keys will be lower case: e.g. A \"Content-Type\" header will be stored as \"content-type\".\n */\nexport function winterCGHeadersToDict(winterCGHeaders: WebFetchHeaders): Record<string, string> {\n const headers: Record<string, string> = {};\n try {\n winterCGHeaders.forEach((value, key) => {\n if (typeof value === 'string') {\n // We check that value is a string even though it might be redundant to make sure prototype pollution is not possible.\n headers[key] = value;\n }\n });\n } catch {\n // just return the empty headers\n }\n\n return headers;\n}\n\n/**\n * Convert common request headers to a simple dictionary.\n */\nexport function headersToDict(reqHeaders: Record<string, string | string[] | undefined>): Record<string, string> {\n const headers: Record<string, string> = Object.create(null);\n\n try {\n Object.entries(reqHeaders).forEach(([key, value]) => {\n if (typeof value === 'string') {\n headers[key] = value;\n }\n });\n } catch {\n // just return the empty headers\n }\n\n return headers;\n}\n\n/**\n * Converts a `Request` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into the format that the `RequestData` integration understands.\n */\nexport function winterCGRequestToRequestData(req: WebFetchRequest): RequestEventData {\n const headers = winterCGHeadersToDict(req.headers);\n\n return {\n method: req.method,\n url: req.url,\n query_string: extractQueryParamsFromUrl(req.url),\n headers,\n // TODO: Can we extract body data from the request?\n };\n}\n\n/**\n * Checks if the content type is textual and safe to capture.\n */\nfunction isTextualContentType(contentType: string | null): boolean {\n if (!contentType) {\n return false;\n }\n const lowerContentType = contentType.toLowerCase();\n return TEXT_CONTENT_TYPES.some(type => lowerContentType.includes(type));\n}\n\n/**\n * Captures the body from a Web Fetch API Request and adds it to the isolation scope.\n *\n * This function clones the request to read the body without affecting the original.\n * Only textual content types are captured - binary data is skipped.\n *\n * This is used by WinterCG-compatible runtimes (Cloudflare Workers, Deno, Bun, Vercel Edge, etc.)\n * that use the Web Fetch API Request object.\n *\n * @param request - The incoming Web Fetch API Request\n * @param isolationScope - The isolation scope to add the body to\n * @param maxRequestBodySize - The maximum size of the request body to capture ('small' = 1KB, 'medium' = 10KB, 'always' = 1MB)\n */\nexport async function captureBodyFromWinterCGRequest(\n request: WebFetchRequest,\n isolationScope: Scope,\n maxRequestBodySize: Exclude<MaxRequestBodySize, 'none'>,\n): Promise<void> {\n try {\n const contentType = request.headers.get('content-type');\n\n if (!isTextualContentType(contentType)) {\n DEBUG_BUILD && debug.log('Skipping body capture for non-textual content type:', contentType);\n return;\n }\n\n if (!request.body) {\n return;\n }\n\n const contentLength = request.headers.get('content-length');\n const maxBodySize = getMaxBodyByteLength(maxRequestBodySize);\n\n if (contentLength) {\n const length = parseInt(contentLength, 10);\n if (!isNaN(length) && length > MAX_BODY_BYTE_LENGTH) {\n DEBUG_BUILD && debug.log('Skipping body capture: body too large', length);\n return;\n }\n }\n\n const clonedRequest = request.clone();\n const bodyPromise = clonedRequest.text();\n const timeoutPromise = new Promise<null>(resolve => {\n safeUnref(setTimeout(() => resolve(null), 2000));\n });\n\n const body = await Promise.race([bodyPromise, timeoutPromise]);\n\n if (body === null) {\n DEBUG_BUILD && debug.log('Timeout reading request body');\n return;\n }\n\n if (!body) {\n return;\n }\n\n // Using TextEncoder to get byte length for UTF-8 strings\n const encoder = new TextEncoder();\n const bytes = encoder.encode(body);\n const bodyByteLength = bytes.length;\n\n let truncatedBody: string;\n if (bodyByteLength > maxBodySize) {\n const decoder = new TextDecoder();\n truncatedBody = `${decoder.decode(bytes.slice(0, maxBodySize - 3))}...`;\n } else {\n truncatedBody = body;\n }\n\n isolationScope.setSDKProcessingMetadata({ normalizedRequest: { data: truncatedBody } });\n\n DEBUG_BUILD && debug.log('Captured request body:', bodyByteLength, 'bytes');\n } catch (error) {\n DEBUG_BUILD && debug.error('Error capturing request body:', error);\n }\n}\n\n/**\n * Convert a HTTP request object to RequestEventData to be passed as normalizedRequest.\n * Instead of allowing `PolymorphicRequest` to be passed,\n * we want to be more specific and generally require a http.IncomingMessage-like object.\n */\nexport function httpRequestToRequestData(request: {\n method?: string;\n url?: string;\n headers?: {\n [key: string]: string | string[] | undefined;\n };\n protocol?: string;\n socket?: {\n encrypted?: boolean;\n remoteAddress?: string;\n };\n}): RequestEventData {\n const headers = request.headers || {};\n\n // Check for x-forwarded-host first, then fall back to host header\n const forwardedHost = typeof headers['x-forwarded-host'] === 'string' ? headers['x-forwarded-host'] : undefined;\n const host = forwardedHost || (typeof headers.host === 'string' ? headers.host : undefined);\n\n // Check for x-forwarded-proto first, then fall back to existing protocol detection\n const forwardedProto = typeof headers['x-forwarded-proto'] === 'string' ? headers['x-forwarded-proto'] : undefined;\n const protocol = forwardedProto || request.protocol || (request.socket?.encrypted ? 'https' : 'http');\n\n const url = request.url || '';\n\n const absoluteUrl = getAbsoluteUrl({\n url,\n host,\n protocol,\n });\n\n // This is non-standard, but may be sometimes set\n // It may be overwritten later by our own body handling\n const data = (request as PolymorphicRequest).body || undefined;\n\n // This is non-standard, but may be set on e.g. Next.js or Express requests\n const cookies = (request as PolymorphicRequest).cookies;\n\n return {\n url: absoluteUrl,\n method: request.method,\n query_string: extractQueryParamsFromUrl(url),\n headers: headersToDict(headers),\n cookies,\n data,\n };\n}\n\nfunction getAbsoluteUrl({\n url,\n protocol,\n host,\n}: {\n url?: string;\n protocol: string;\n host?: string;\n}): string | undefined {\n if (url?.startsWith('http')) {\n return url;\n }\n\n if (url && host) {\n return `${protocol}://${host}${url}`;\n }\n\n return undefined;\n}\n\nconst SENSITIVE_HEADER_SNIPPETS = [\n 'auth',\n 'token',\n 'secret',\n 'session', // for the user_session cookie\n 'password',\n 'passwd',\n 'pwd',\n 'key',\n 'jwt',\n 'bearer',\n 'sso',\n 'saml',\n 'csrf',\n 'xsrf',\n 'credentials',\n // Always treat cookie headers as sensitive in case individual key-value cookie pairs cannot properly be extracted\n 'set-cookie',\n 'cookie',\n];\n\n/**\n * Extra substrings matched only against individual Cookie / Set-Cookie **names** (not header names),\n * so we can cover common session secrets that do not match {@link SENSITIVE_HEADER_SNIPPETS}\n * (e.g. `connect.sid` does not contain `session`) without false positives on arbitrary HTTP headers.\n *\n * Cookie names are checked with the same `includes()` list as headers plus these entries; omit redundant\n * cookie-only snippets that are already implied by a header match (e.g. `oauth` → `auth`, `id_token` → `token`,\n * `next-auth` → `auth`).\n */\nconst SENSITIVE_COOKIE_NAME_SNIPPETS = [\n // Express / Connect default session cookie\n '.sid',\n // Opaque session ids (PHPSESSID, ASPSESSIONID*, BIGipServer*, *sessid*, …)\n 'sessid',\n // Laravel etc. \"remember me\" tokens\n 'remember',\n // OIDC / OAuth auxiliary (`oauth*` covered by header snippet `auth`)\n 'oidc',\n 'pkce',\n 'nonce',\n // RFC 6265bis high-security cookie name prefixes\n '__secure-',\n '__host-',\n // Load balancer / CDN sticky-session cookies (opaque routing tokens)\n 'awsalb',\n 'awselb',\n 'akamai',\n // BaaS / IdP session cookies (names often omit \"session\")\n '__stripe',\n 'cognito',\n 'firebase',\n 'supabase',\n 'sb-',\n // Step-up / MFA cookies\n 'mfa',\n '2fa',\n];\n\nconst PII_HEADER_SNIPPETS = ['x-forwarded-', '-user'];\n\n/**\n * Converts incoming HTTP request or response headers to OpenTelemetry span attributes following semantic conventions.\n * Header names are converted to the format: http.<request|response>.header.<key>\n * where <key> is the header name in lowercase with dashes converted to underscores.\n *\n * @param lifecycle - The lifecycle of the headers, either 'request' or 'response'\n *\n * @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/#http-request-header\n * @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/#http-response-header\n *\n * @see https://getsentry.github.io/sentry-conventions/attributes/http/#http-request-header-key\n * @see https://getsentry.github.io/sentry-conventions/attributes/http/#http-response-header-key\n */\nexport function httpHeadersToSpanAttributes(\n headers: Record<string, string | string[] | undefined>,\n sendDefaultPii: boolean = false,\n lifecycle: 'request' | 'response' = 'request',\n): Record<string, string> {\n const spanAttributes: Record<string, string> = {};\n\n try {\n Object.entries(headers).forEach(([key, value]) => {\n if (value == null) {\n return;\n }\n\n const lowerCasedHeaderKey = key.toLowerCase();\n const isCookieHeader = lowerCasedHeaderKey === 'cookie' || lowerCasedHeaderKey === 'set-cookie';\n\n if (isCookieHeader && typeof value === 'string' && value !== '') {\n // Set-Cookie: single cookie with attributes (\"name=value; HttpOnly; Secure\")\n // Cookie: multiple cookies separated by \"; \" (\"cookie1=value1; cookie2=value2\")\n const isSetCookie = lowerCasedHeaderKey === 'set-cookie';\n const semicolonIndex = value.indexOf(';');\n const cookieString = isSetCookie && semicolonIndex !== -1 ? value.substring(0, semicolonIndex) : value;\n const cookies = isSetCookie ? [cookieString] : cookieString.split('; ');\n\n for (const cookie of cookies) {\n // Split only at the first '=' to preserve '=' characters in cookie values\n const equalSignIndex = cookie.indexOf('=');\n const cookieKey = equalSignIndex !== -1 ? cookie.substring(0, equalSignIndex) : cookie;\n const cookieValue = equalSignIndex !== -1 ? cookie.substring(equalSignIndex + 1) : '';\n\n const lowerCasedCookieKey = cookieKey.toLowerCase();\n\n addSpanAttribute({\n spanAttributes,\n headerKey: lowerCasedHeaderKey,\n cookieKey: lowerCasedCookieKey,\n value: cookieValue,\n sendDefaultPii,\n lifecycle,\n });\n }\n } else {\n addSpanAttribute({\n spanAttributes,\n headerKey: lowerCasedHeaderKey,\n value,\n sendDefaultPii,\n lifecycle,\n });\n }\n });\n } catch {\n // Return empty object if there's an error\n }\n\n return spanAttributes;\n}\n\nfunction normalizeAttributeKey(key: string): string {\n return key.replace(/-/g, '_');\n}\n\ntype AddSpanAttributeOptions = {\n spanAttributes: Record<string, string>;\n /** Lowercased HTTP header name (e.g. `cookie`, `set-cookie`, `accept`). */\n headerKey: string;\n /**\n * Lowercased cookie name when this attribute comes from a parsed `Cookie` / `Set-Cookie` value.\n * Omit for non-cookie headers; when present and non-empty, cookie-specific sensitivity rules apply.\n */\n cookieKey?: string;\n value: string | string[] | undefined;\n sendDefaultPii: boolean;\n lifecycle: 'request' | 'response';\n};\n\nfunction addSpanAttribute({\n spanAttributes,\n headerKey,\n cookieKey,\n value,\n sendDefaultPii,\n lifecycle,\n}: AddSpanAttributeOptions): void {\n const isCookieSubKey = Boolean(cookieKey);\n const nameForSensitivity = cookieKey || headerKey;\n const headerValue = handleHttpHeader(nameForSensitivity, value, sendDefaultPii, isCookieSubKey);\n if (headerValue == null) {\n return;\n }\n\n const normalizedKey = `http.${lifecycle}.header.${normalizeAttributeKey(headerKey)}${cookieKey ? `.${normalizeAttributeKey(cookieKey)}` : ''}`;\n spanAttributes[normalizedKey] = headerValue;\n}\n\nfunction handleHttpHeader(\n lowerCasedKey: string,\n value: string | string[] | undefined,\n sendPii: boolean,\n isCookieSubKey: boolean = false,\n): string | undefined {\n const snippetsForSensitivity = isCookieSubKey\n ? [...SENSITIVE_HEADER_SNIPPETS, ...SENSITIVE_COOKIE_NAME_SNIPPETS]\n : SENSITIVE_HEADER_SNIPPETS;\n\n const isSensitive = sendPii\n ? snippetsForSensitivity.some(snippet => lowerCasedKey.includes(snippet))\n : [...PII_HEADER_SNIPPETS, ...snippetsForSensitivity].some(snippet => lowerCasedKey.includes(snippet));\n\n if (isSensitive) {\n return '[Filtered]';\n } else if (Array.isArray(value)) {\n return value.map(v => (v != null ? String(v) : v)).join(';');\n } else if (typeof value === 'string') {\n return value;\n }\n\n return undefined;\n}\n\n/** Extract the query params from an URL. */\nexport function extractQueryParamsFromUrl(url: string): string | undefined {\n // url is path and query string\n if (!url) {\n return;\n }\n\n try {\n // The `URL` constructor can't handle internal URLs of the form `/some/path/here`, so stick a dummy protocol and\n // hostname as the base. Since the point here is just to grab the query string, it doesn't matter what we use.\n const queryParams = new URL(url, 'http://s.io').search.slice(1);\n return queryParams.length ? queryParams : undefined;\n } catch {\n return undefined;\n }\n}\n"],"names":["DEBUG_BUILD","debug","safeUnref"],"mappings":";;;;;;AAAA;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACO,MAAM,oBAAA,GAAuB,IAAA,GAAQ;;AAE5C;AACA,MAAM,qBAAqB;AAC3B,EAAE,OAAO;AACT,EAAE,kBAAkB;AACpB,EAAE,mCAAmC;AACrC,EAAE,iBAAiB;AACnB,EAAE,qBAAqB;AACvB,CAAC;;AAED;AACA;AACA;AACO,SAAS,oBAAoB,CAAC,kBAAkB,EAA+C;AACtG,EAAE,IAAI,kBAAA,KAAuB,OAAO,EAAE,OAAO,IAAK;AAClD,EAAE,IAAI,kBAAA,KAAuB,QAAQ,EAAE,OAAO,KAAM;AACpD,EAAE,OAAO,oBAAoB;AAC7B;;AAEA;AACA;AACA;AACA;AACO,SAAS,qBAAqB,CAAC,eAAe,EAA2C;AAChG,EAAE,MAAM,OAAO,GAA2B,EAAE;AAC5C,EAAE,IAAI;AACN,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK;AAC5C,MAAM,IAAI,OAAO,KAAA,KAAU,QAAQ,EAAE;AACrC;AACA,QAAQ,OAAO,CAAC,GAAG,CAAA,GAAI,KAAK;AAC5B,MAAM;AACN,IAAI,CAAC,CAAC;AACN,EAAE,EAAE,MAAM;AACV;AACA,EAAE;;AAEF,EAAE,OAAO,OAAO;AAChB;;AAEA;AACA;AACA;AACO,SAAS,aAAa,CAAC,UAAU,EAAyE;AACjH,EAAE,MAAM,OAAO,GAA2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AAE7D,EAAE,IAAI;AACN,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK;AACzD,MAAM,IAAI,OAAO,KAAA,KAAU,QAAQ,EAAE;AACrC,QAAQ,OAAO,CAAC,GAAG,CAAA,GAAI,KAAK;AAC5B,MAAM;AACN,IAAI,CAAC,CAAC;AACN,EAAE,EAAE,MAAM;AACV;AACA,EAAE;;AAEF,EAAE,OAAO,OAAO;AAChB;;AAEA;AACA;AACA;AACO,SAAS,4BAA4B,CAAC,GAAG,EAAqC;AACrF,EAAE,MAAM,UAAU,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC;;AAEpD,EAAE,OAAO;AACT,IAAI,MAAM,EAAE,GAAG,CAAC,MAAM;AACtB,IAAI,GAAG,EAAE,GAAG,CAAC,GAAG;AAChB,IAAI,YAAY,EAAE,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC;AACpD,IAAI,OAAO;AACX;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC,WAAW,EAA0B;AACnE,EAAE,IAAI,CAAC,WAAW,EAAE;AACpB,IAAI,OAAO,KAAK;AAChB,EAAE;AACF,EAAE,MAAM,gBAAA,GAAmB,WAAW,CAAC,WAAW,EAAE;AACpD,EAAE,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAA,IAAQ,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACzE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,8BAA8B;AACpD,EAAE,OAAO;AACT,EAAE,cAAc;AAChB,EAAE,kBAAkB;AACpB,EAAiB;AACjB,EAAE,IAAI;AACN,IAAI,MAAM,WAAA,GAAc,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;;AAE3D,IAAI,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,EAAE;AAC5C,MAAMA,sBAAA,IAAeC,iBAAK,CAAC,GAAG,CAAC,qDAAqD,EAAE,WAAW,CAAC;AAClG,MAAM;AACN,IAAI;;AAEJ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;AACvB,MAAM;AACN,IAAI;;AAEJ,IAAI,MAAM,aAAA,GAAgB,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAC/D,IAAI,MAAM,WAAA,GAAc,oBAAoB,CAAC,kBAAkB,CAAC;;AAEhE,IAAI,IAAI,aAAa,EAAE;AACvB,MAAM,MAAM,SAAS,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC;AAChD,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAA,IAAK,MAAA,GAAS,oBAAoB,EAAE;AAC3D,QAAQD,sBAAA,IAAeC,iBAAK,CAAC,GAAG,CAAC,uCAAuC,EAAE,MAAM,CAAC;AACjF,QAAQ;AACR,MAAM;AACN,IAAI;;AAEJ,IAAI,MAAM,aAAA,GAAgB,OAAO,CAAC,KAAK,EAAE;AACzC,IAAI,MAAM,WAAA,GAAc,aAAa,CAAC,IAAI,EAAE;AAC5C,IAAI,MAAM,cAAA,GAAiB,IAAI,OAAO,CAAO,WAAW;AACxD,MAAMC,eAAS,CAAC,UAAU,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AACtD,IAAI,CAAC,CAAC;;AAEN,IAAI,MAAM,IAAA,GAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;;AAElE,IAAI,IAAI,IAAA,KAAS,IAAI,EAAE;AACvB,MAAMF,0BAAeC,iBAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC;AAC9D,MAAM;AACN,IAAI;;AAEJ,IAAI,IAAI,CAAC,IAAI,EAAE;AACf,MAAM;AACN,IAAI;;AAEJ;AACA,IAAI,MAAM,OAAA,GAAU,IAAI,WAAW,EAAE;AACrC,IAAI,MAAM,QAAQ,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;AACtC,IAAI,MAAM,cAAA,GAAiB,KAAK,CAAC,MAAM;;AAEvC,IAAI,IAAI,aAAa;AACrB,IAAI,IAAI,cAAA,GAAiB,WAAW,EAAE;AACtC,MAAM,MAAM,OAAA,GAAU,IAAI,WAAW,EAAE;AACvC,MAAM,aAAA,GAAgB,CAAC,EAAA,OAAA,CAAA,MAAA,CAAA,KAAA,CAAA,KAAA,CAAA,CAAA,EAAA,WAAA,GAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CAAA;AACA,IAAA,CAAA,MAAA;AACA,MAAA,aAAA,GAAA,IAAA;AACA,IAAA;;AAEA,IAAA,cAAA,CAAA,wBAAA,CAAA,EAAA,iBAAA,EAAA,EAAA,IAAA,EAAA,aAAA,EAAA,EAAA,CAAA;;AAEA,IAAAD,sBAAA,IAAAC,iBAAA,CAAA,GAAA,CAAA,wBAAA,EAAA,cAAA,EAAA,OAAA,CAAA;AACA,EAAA,CAAA,CAAA,OAAA,KAAA,EAAA;AACA,IAAAD,sBAAA,IAAAC,iBAAA,CAAA,KAAA,CAAA,+BAAA,EAAA,KAAA,CAAA;AACA,EAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAA,wBAAA,CAAA;;AAWA,EAAA;AACA,EAAA,MAAA,OAAA,GAAA,OAAA,CAAA,OAAA,IAAA,EAAA;;AAEA;AACA,EAAA,MAAA,aAAA,GAAA,OAAA,OAAA,CAAA,kBAAA,CAAA,KAAA,QAAA,GAAA,OAAA,CAAA,kBAAA,CAAA,GAAA,SAAA;AACA,EAAA,MAAA,IAAA,GAAA,aAAA,KAAA,OAAA,OAAA,CAAA,IAAA,KAAA,QAAA,GAAA,OAAA,CAAA,IAAA,GAAA,SAAA,CAAA;;AAEA;AACA,EAAA,MAAA,cAAA,GAAA,OAAA,OAAA,CAAA,mBAAA,CAAA,KAAA,QAAA,GAAA,OAAA,CAAA,mBAAA,CAAA,GAAA,SAAA;AACA,EAAA,MAAA,QAAA,GAAA,cAAA,IAAA,OAAA,CAAA,QAAA,KAAA,OAAA,CAAA,MAAA,EAAA,SAAA,GAAA,OAAA,GAAA,MAAA,CAAA;;AAEA,EAAA,MAAA,GAAA,GAAA,OAAA,CAAA,GAAA,IAAA,EAAA;;AAEA,EAAA,MAAA,WAAA,GAAA,cAAA,CAAA;AACA,IAAA,GAAA;AACA,IAAA,IAAA;AACA,IAAA,QAAA;AACA,GAAA,CAAA;;AAEA;AACA;AACA,EAAA,MAAA,IAAA,GAAA,CAAA,OAAA,GAAA,IAAA,IAAA,SAAA;;AAEA;AACA,EAAA,MAAA,OAAA,GAAA,CAAA,OAAA,GAAA,OAAA;;AAEA,EAAA,OAAA;AACA,IAAA,GAAA,EAAA,WAAA;AACA,IAAA,MAAA,EAAA,OAAA,CAAA,MAAA;AACA,IAAA,YAAA,EAAA,yBAAA,CAAA,GAAA,CAAA;AACA,IAAA,OAAA,EAAA,aAAA,CAAA,OAAA,CAAA;AACA,IAAA,OAAA;AACA,IAAA,IAAA;AACA,GAAA;AACA;;AAEA,SAAA,cAAA,CAAA;AACA,EAAA,GAAA;AACA,EAAA,QAAA;AACA,EAAA,IAAA;AACA;;AAIA,EAAA;AACA,EAAA,IAAA,GAAA,EAAA,UAAA,CAAA,MAAA,CAAA,EAAA;AACA,IAAA,OAAA,GAAA;AACA,EAAA;;AAEA,EAAA,IAAA,GAAA,IAAA,IAAA,EAAA;AACA,IAAA,OAAA,CAAA,EAAA,QAAA,CAAA,GAAA,EAAA,IAAA,CAAA,EAAA,GAAA,CAAA,CAAA;AACA,EAAA;;AAEA,EAAA,OAAA,SAAA;AACA;;AAEA,MAAA,yBAAA,GAAA;AACA,EAAA,MAAA;AACA,EAAA,OAAA;AACA,EAAA,QAAA;AACA,EAAA,SAAA;AACA,EAAA,UAAA;AACA,EAAA,QAAA;AACA,EAAA,KAAA;AACA,EAAA,KAAA;AACA,EAAA,KAAA;AACA,EAAA,QAAA;AACA,EAAA,KAAA;AACA,EAAA,MAAA;AACA,EAAA,MAAA;AACA,EAAA,MAAA;AACA,EAAA,aAAA;AACA;AACA,EAAA,YAAA;AACA,EAAA,QAAA;AACA,CAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA,8BAAA,GAAA;AACA;AACA,EAAA,MAAA;AACA;AACA,EAAA,QAAA;AACA;AACA,EAAA,UAAA;AACA;AACA,EAAA,MAAA;AACA,EAAA,MAAA;AACA,EAAA,OAAA;AACA;AACA,EAAA,WAAA;AACA,EAAA,SAAA;AACA;AACA,EAAA,QAAA;AACA,EAAA,QAAA;AACA,EAAA,QAAA;AACA;AACA,EAAA,UAAA;AACA,EAAA,SAAA;AACA,EAAA,UAAA;AACA,EAAA,UAAA;AACA,EAAA,KAAA;AACA;AACA,EAAA,KAAA;AACA,EAAA,KAAA;AACA,CAAA;;AAEA,MAAA,mBAAA,GAAA,CAAA,cAAA,EAAA,OAAA,CAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,2BAAA;AACA,EAAA,OAAA;AACA,EAAA,cAAA,GAAA,KAAA;AACA,EAAA,SAAA,GAAA,SAAA;AACA,EAAA;AACA,EAAA,MAAA,cAAA,GAAA,EAAA;;AAEA,EAAA,IAAA;AACA,IAAA,MAAA,CAAA,OAAA,CAAA,OAAA,CAAA,CAAA,OAAA,CAAA,CAAA,CAAA,GAAA,EAAA,KAAA,CAAA,KAAA;AACA,MAAA,IAAA,KAAA,IAAA,IAAA,EAAA;AACA,QAAA;AACA,MAAA;;AAEA,MAAA,MAAA,mBAAA,GAAA,GAAA,CAAA,WAAA,EAAA;AACA,MAAA,MAAA,cAAA,GAAA,mBAAA,KAAA,QAAA,IAAA,mBAAA,KAAA,YAAA;;AAEA,MAAA,IAAA,cAAA,IAAA,OAAA,KAAA,KAAA,QAAA,IAAA,KAAA,KAAA,EAAA,EAAA;AACA;AACA;AACA,QAAA,MAAA,WAAA,GAAA,mBAAA,KAAA,YAAA;AACA,QAAA,MAAA,cAAA,GAAA,KAAA,CAAA,OAAA,CAAA,GAAA,CAAA;AACA,QAAA,MAAA,YAAA,GAAA,WAAA,IAAA,cAAA,KAAA,CAAA,CAAA,GAAA,KAAA,CAAA,SAAA,CAAA,CAAA,EAAA,cAAA,CAAA,GAAA,KAAA;AACA,QAAA,MAAA,OAAA,GAAA,WAAA,GAAA,CAAA,YAAA,CAAA,GAAA,YAAA,CAAA,KAAA,CAAA,IAAA,CAAA;;AAEA,QAAA,KAAA,MAAA,MAAA,IAAA,OAAA,EAAA;AACA;AACA,UAAA,MAAA,cAAA,GAAA,MAAA,CAAA,OAAA,CAAA,GAAA,CAAA;AACA,UAAA,MAAA,SAAA,GAAA,cAAA,KAAA,CAAA,CAAA,GAAA,MAAA,CAAA,SAAA,CAAA,CAAA,EAAA,cAAA,CAAA,GAAA,MAAA;AACA,UAAA,MAAA,WAAA,GAAA,cAAA,KAAA,CAAA,CAAA,GAAA,MAAA,CAAA,SAAA,CAAA,cAAA,GAAA,CAAA,CAAA,GAAA,EAAA;;AAEA,UAAA,MAAA,mBAAA,GAAA,SAAA,CAAA,WAAA,EAAA;;AAEA,UAAA,gBAAA,CAAA;AACA,YAAA,cAAA;AACA,YAAA,SAAA,EAAA,mBAAA;AACA,YAAA,SAAA,EAAA,mBAAA;AACA,YAAA,KAAA,EAAA,WAAA;AACA,YAAA,cAAA;AACA,YAAA,SAAA;AACA,WAAA,CAAA;AACA,QAAA;AACA,MAAA,CAAA,MAAA;AACA,QAAA,gBAAA,CAAA;AACA,UAAA,cAAA;AACA,UAAA,SAAA,EAAA,mBAAA;AACA,UAAA,KAAA;AACA,UAAA,cAAA;AACA,UAAA,SAAA;AACA,SAAA,CAAA;AACA,MAAA;AACA,IAAA,CAAA,CAAA;AACA,EAAA,CAAA,CAAA,MAAA;AACA;AACA,EAAA;;AAEA,EAAA,OAAA,cAAA;AACA;;AAEA,SAAA,qBAAA,CAAA,GAAA,EAAA;AACA,EAAA,OAAA,GAAA,CAAA,OAAA,CAAA,IAAA,EAAA,GAAA,CAAA;AACA;;AAgBA,SAAA,gBAAA,CAAA;AACA,EAAA,cAAA;AACA,EAAA,SAAA;AACA,EAAA,SAAA;AACA,EAAA,KAAA;AACA,EAAA,cAAA;AACA,EAAA,SAAA;AACA,CAAA,EAAA;AACA,EAAA,MAAA,cAAA,GAAA,OAAA,CAAA,SAAA,CAAA;AACA,EAAA,MAAA,kBAAA,GAAA,SAAA,IAAA,SAAA;AACA,EAAA,MAAA,WAAA,GAAA,gBAAA,CAAA,kBAAA,EAAA,KAAA,EAAA,cAAA,EAAA,cAAA,CAAA;AACA,EAAA,IAAA,WAAA,IAAA,IAAA,EAAA;AACA,IAAA;AACA,EAAA;;AAEA,EAAA,MAAA,aAAA,GAAA,CAAA,KAAA,EAAA,SAAA,CAAA,QAAA,EAAA,qBAAA,CAAA,SAAA,CAAA,CAAA,EAAA,SAAA,GAAA,CAAA,CAAA,EAAA,qBAAA,CAAA,SAAA,CAAA,CAAA,CAAA,GAAA,EAAA,CAAA,CAAA;AACA,EAAA,cAAA,CAAA,aAAA,CAAA,GAAA,WAAA;AACA;;AAEA,SAAA,gBAAA;AACA,EAAA,aAAA;AACA,EAAA,KAAA;AACA,EAAA,OAAA;AACA,EAAA,cAAA,GAAA,KAAA;AACA,EAAA;AACA,EAAA,MAAA,sBAAA,GAAA;AACA,MAAA,CAAA,GAAA,yBAAA,EAAA,GAAA,8BAAA;AACA,MAAA,yBAAA;;AAEA,EAAA,MAAA,WAAA,GAAA;AACA,MAAA,sBAAA,CAAA,IAAA,CAAA,OAAA,IAAA,aAAA,CAAA,QAAA,CAAA,OAAA,CAAA;AACA,MAAA,CAAA,GAAA,mBAAA,EAAA,GAAA,sBAAA,CAAA,CAAA,IAAA,CAAA,OAAA,IAAA,aAAA,CAAA,QAAA,CAAA,OAAA,CAAA,CAAA;;AAEA,EAAA,IAAA,WAAA,EAAA;AACA,IAAA,OAAA,YAAA;AACA,EAAA,CAAA,MAAA,IAAA,KAAA,CAAA,OAAA,CAAA,KAAA,CAAA,EAAA;AACA,IAAA,OAAA,KAAA,CAAA,GAAA,CAAA,CAAA,KAAA,CAAA,IAAA,IAAA,GAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,IAAA,CAAA,GAAA,CAAA;AACA,EAAA,CAAA,MAAA,IAAA,OAAA,KAAA,KAAA,QAAA,EAAA;AACA,IAAA,OAAA,KAAA;AACA,EAAA;;AAEA,EAAA,OAAA,SAAA;AACA;;AAEA;AACA,SAAA,yBAAA,CAAA,GAAA,EAAA;AACA;AACA,EAAA,IAAA,CAAA,GAAA,EAAA;AACA,IAAA;AACA,EAAA;;AAEA,EAAA,IAAA;AACA;AACA;AACA,IAAA,MAAA,WAAA,GAAA,IAAA,GAAA,CAAA,GAAA,EAAA,aAAA,CAAA,CAAA,MAAA,CAAA,KAAA,CAAA,CAAA,CAAA;AACA,IAAA,OAAA,WAAA,CAAA,MAAA,GAAA,WAAA,GAAA,SAAA;AACA,EAAA,CAAA,CAAA,MAAA;AACA,IAAA,OAAA,SAAA;AACA,EAAA;AACA;;;;;;;;;;;;"}
|