@sentry/cloudflare 9.31.0 → 9.33.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/build/cjs/client.js +18 -3
- package/build/cjs/client.js.map +1 -1
- package/build/cjs/durableobject.js +5 -3
- package/build/cjs/durableobject.js.map +1 -1
- package/build/cjs/flush.js +36 -0
- package/build/cjs/flush.js.map +1 -0
- package/build/cjs/handler.js +13 -8
- package/build/cjs/handler.js.map +1 -1
- package/build/cjs/index.js +4 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/tracing/vercelai.js +45 -0
- package/build/cjs/integrations/tracing/vercelai.js.map +1 -0
- package/build/cjs/opentelemetry/tracer.js +78 -0
- package/build/cjs/opentelemetry/tracer.js.map +1 -0
- package/build/cjs/pages-plugin.js +3 -1
- package/build/cjs/pages-plugin.js.map +1 -1
- package/build/cjs/request.js +5 -3
- package/build/cjs/request.js.map +1 -1
- package/build/cjs/sdk.js +20 -1
- package/build/cjs/sdk.js.map +1 -1
- package/build/cjs/workflows.js +161 -0
- package/build/cjs/workflows.js.map +1 -0
- package/build/esm/client.js +18 -3
- package/build/esm/client.js.map +1 -1
- package/build/esm/durableobject.js +5 -3
- package/build/esm/durableobject.js.map +1 -1
- package/build/esm/flush.js +34 -0
- package/build/esm/flush.js.map +1 -0
- package/build/esm/handler.js +13 -8
- package/build/esm/handler.js.map +1 -1
- package/build/esm/index.js +2 -0
- package/build/esm/index.js.map +1 -1
- package/build/esm/integrations/tracing/vercelai.js +43 -0
- package/build/esm/integrations/tracing/vercelai.js.map +1 -0
- package/build/esm/opentelemetry/tracer.js +76 -0
- package/build/esm/opentelemetry/tracer.js.map +1 -0
- package/build/esm/package.json +1 -1
- package/build/esm/pages-plugin.js +3 -1
- package/build/esm/pages-plugin.js.map +1 -1
- package/build/esm/request.js +5 -3
- package/build/esm/request.js.map +1 -1
- package/build/esm/sdk.js +20 -1
- package/build/esm/sdk.js.map +1 -1
- package/build/esm/workflows.js +159 -0
- package/build/esm/workflows.js.map +1 -0
- package/build/types/client.d.ts +32 -1
- package/build/types/client.d.ts.map +1 -1
- package/build/types/durableobject.d.ts.map +1 -1
- package/build/types/flush.d.ts +16 -0
- package/build/types/flush.d.ts.map +1 -0
- package/build/types/handler.d.ts.map +1 -1
- package/build/types/index.d.ts +2 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/vercelai.d.ts +37 -0
- package/build/types/integrations/tracing/vercelai.d.ts.map +1 -0
- package/build/types/opentelemetry/tracer.d.ts +6 -0
- package/build/types/opentelemetry/tracer.d.ts.map +1 -0
- package/build/types/pages-plugin.d.ts.map +1 -1
- package/build/types/request.d.ts +1 -0
- package/build/types/request.d.ts.map +1 -1
- package/build/types/scope-utils.d.ts +1 -0
- package/build/types/scope-utils.d.ts.map +1 -1
- package/build/types/sdk.d.ts.map +1 -1
- package/build/types/utils/addOriginToSpan.d.ts +5 -0
- package/build/types/utils/addOriginToSpan.d.ts.map +1 -0
- package/build/types/utils/commonjs.d.ts +3 -0
- package/build/types/utils/commonjs.d.ts.map +1 -0
- package/build/types/workflows.d.ts +25 -0
- package/build/types/workflows.d.ts.map +1 -0
- package/build/types-ts3.8/client.d.ts +32 -1
- package/build/types-ts3.8/flush.d.ts +16 -0
- package/build/types-ts3.8/index.d.ts +2 -0
- package/build/types-ts3.8/integrations/tracing/vercelai.d.ts +37 -0
- package/build/types-ts3.8/opentelemetry/tracer.d.ts +6 -0
- package/build/types-ts3.8/request.d.ts +1 -0
- package/build/types-ts3.8/scope-utils.d.ts +1 -0
- package/build/types-ts3.8/utils/addOriginToSpan.d.ts +5 -0
- package/build/types-ts3.8/utils/commonjs.d.ts +3 -0
- package/build/types-ts3.8/workflows.d.ts +22 -0
- package/package.json +4 -3
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { defineIntegration, addVercelAiProcessors } from '@sentry/core';
|
|
2
|
+
|
|
3
|
+
const INTEGRATION_NAME = 'VercelAI';
|
|
4
|
+
|
|
5
|
+
const _vercelAIIntegration = (() => {
|
|
6
|
+
return {
|
|
7
|
+
name: INTEGRATION_NAME,
|
|
8
|
+
setup(client) {
|
|
9
|
+
addVercelAiProcessors(client);
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}) ;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Adds Sentry tracing instrumentation for the [ai](https://www.npmjs.com/package/ai) library.
|
|
16
|
+
* This integration is not enabled by default, you need to manually add it.
|
|
17
|
+
*
|
|
18
|
+
* For more information, see the [`ai` documentation](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry).
|
|
19
|
+
*
|
|
20
|
+
* You need to enable collecting spans for a specific call by setting
|
|
21
|
+
* `experimental_telemetry.isEnabled` to `true` in the first argument of the function call.
|
|
22
|
+
*
|
|
23
|
+
* ```javascript
|
|
24
|
+
* const result = await generateText({
|
|
25
|
+
* model: openai('gpt-4-turbo'),
|
|
26
|
+
* experimental_telemetry: { isEnabled: true },
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* If you want to collect inputs and outputs for a specific call, you must specifically opt-in to each
|
|
31
|
+
* function call by setting `experimental_telemetry.recordInputs` and `experimental_telemetry.recordOutputs`
|
|
32
|
+
* to `true`.
|
|
33
|
+
*
|
|
34
|
+
* ```javascript
|
|
35
|
+
* const result = await generateText({
|
|
36
|
+
* model: openai('gpt-4-turbo'),
|
|
37
|
+
* experimental_telemetry: { isEnabled: true, recordInputs: true, recordOutputs: true },
|
|
38
|
+
* });
|
|
39
|
+
*/
|
|
40
|
+
const vercelAIIntegration = defineIntegration(_vercelAIIntegration);
|
|
41
|
+
|
|
42
|
+
export { vercelAIIntegration };
|
|
43
|
+
//# sourceMappingURL=vercelai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vercelai.js","sources":["../../../../src/integrations/tracing/vercelai.ts"],"sourcesContent":["/**\n * This is a copy of the Vercel AI integration from the node SDK.\n *\n * The only difference is that it does not use `@opentelemetry/instrumentation`\n * because Cloudflare Workers do not support it.\n *\n * Therefore, we cannot automatically patch setting `experimental_telemetry: { isEnabled: true }`\n * and users have to manually set this to get spans.\n */\n\nimport type { IntegrationFn } from '@sentry/core';\nimport { addVercelAiProcessors, defineIntegration } from '@sentry/core';\n\nconst INTEGRATION_NAME = 'VercelAI';\n\nconst _vercelAIIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n addVercelAiProcessors(client);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [ai](https://www.npmjs.com/package/ai) library.\n * This integration is not enabled by default, you need to manually add it.\n *\n * For more information, see the [`ai` documentation](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry).\n *\n * You need to enable collecting spans for a specific call by setting\n * `experimental_telemetry.isEnabled` to `true` in the first argument of the function call.\n *\n * ```javascript\n * const result = await generateText({\n * model: openai('gpt-4-turbo'),\n * experimental_telemetry: { isEnabled: true },\n * });\n * ```\n *\n * If you want to collect inputs and outputs for a specific call, you must specifically opt-in to each\n * function call by setting `experimental_telemetry.recordInputs` and `experimental_telemetry.recordOutputs`\n * to `true`.\n *\n * ```javascript\n * const result = await generateText({\n * model: openai('gpt-4-turbo'),\n * experimental_telemetry: { isEnabled: true, recordInputs: true, recordOutputs: true },\n * });\n */\nexport const vercelAIIntegration = defineIntegration(_vercelAIIntegration);\n"],"names":[],"mappings":";;AAaA,MAAM,gBAAA,GAAmB,UAAU;;AAEnC,MAAM,oBAAqB,IAAG,MAAM;AACpC,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,MAAM,qBAAqB,CAAC,MAAM,CAAC;AACnC,KAAK;AACL,GAAG;AACH,CAAC,CAAE;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,mBAAoB,GAAE,iBAAiB,CAAC,oBAAoB;;;;"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { trace } from '@opentelemetry/api';
|
|
2
|
+
import { startInactiveSpan, startSpanManual } from '@sentry/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Set up a mock OTEL tracer to allow inter-op with OpenTelemetry emitted spans.
|
|
6
|
+
* This is not perfect but handles easy/common use cases.
|
|
7
|
+
*/
|
|
8
|
+
function setupOpenTelemetryTracer() {
|
|
9
|
+
trace.setGlobalTracerProvider(new SentryCloudflareTraceProvider());
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class SentryCloudflareTraceProvider {constructor() { SentryCloudflareTraceProvider.prototype.__init.call(this); }
|
|
13
|
+
__init() {this._tracers = new Map();}
|
|
14
|
+
|
|
15
|
+
getTracer(name, version, options) {
|
|
16
|
+
const key = `${name}@${version || ''}:${options?.schemaUrl || ''}`;
|
|
17
|
+
if (!this._tracers.has(key)) {
|
|
18
|
+
this._tracers.set(key, new SentryCloudflareTracer());
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
22
|
+
return this._tracers.get(key);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class SentryCloudflareTracer {
|
|
27
|
+
startSpan(name, options) {
|
|
28
|
+
return startInactiveSpan({
|
|
29
|
+
name,
|
|
30
|
+
...options,
|
|
31
|
+
attributes: {
|
|
32
|
+
...options?.attributes,
|
|
33
|
+
'sentry.cloudflare_tracer': true,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* NOTE: This does not handle `context` being passed in. It will always put spans on the current scope.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
startActiveSpan(
|
|
43
|
+
name,
|
|
44
|
+
options,
|
|
45
|
+
context,
|
|
46
|
+
fn,
|
|
47
|
+
) {
|
|
48
|
+
const opts = (typeof options === 'object' && options !== null ? options : {}) ;
|
|
49
|
+
|
|
50
|
+
const spanOpts = {
|
|
51
|
+
name,
|
|
52
|
+
...opts,
|
|
53
|
+
attributes: {
|
|
54
|
+
...opts.attributes,
|
|
55
|
+
'sentry.cloudflare_tracer': true,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const callback = (
|
|
60
|
+
typeof options === 'function'
|
|
61
|
+
? options
|
|
62
|
+
: typeof context === 'function'
|
|
63
|
+
? context
|
|
64
|
+
: typeof fn === 'function'
|
|
65
|
+
? fn
|
|
66
|
+
: // eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
67
|
+
() => {}
|
|
68
|
+
) ;
|
|
69
|
+
|
|
70
|
+
// In OTEL the semantic matches `startSpanManual` because spans are not auto-ended
|
|
71
|
+
return startSpanManual(spanOpts, callback) ;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { setupOpenTelemetryTracer };
|
|
76
|
+
//# sourceMappingURL=tracer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracer.js","sources":["../../../src/opentelemetry/tracer.ts"],"sourcesContent":["import type { Context, Span, SpanOptions, Tracer, TracerProvider } from '@opentelemetry/api';\nimport { trace } from '@opentelemetry/api';\nimport { startInactiveSpan, startSpanManual } from '@sentry/core';\n\n/**\n * Set up a mock OTEL tracer to allow inter-op with OpenTelemetry emitted spans.\n * This is not perfect but handles easy/common use cases.\n */\nexport function setupOpenTelemetryTracer(): void {\n trace.setGlobalTracerProvider(new SentryCloudflareTraceProvider());\n}\n\nclass SentryCloudflareTraceProvider implements TracerProvider {\n private readonly _tracers: Map<string, Tracer> = new Map();\n\n public getTracer(name: string, version?: string, options?: { schemaUrl?: string }): Tracer {\n const key = `${name}@${version || ''}:${options?.schemaUrl || ''}`;\n if (!this._tracers.has(key)) {\n this._tracers.set(key, new SentryCloudflareTracer());\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._tracers.get(key)!;\n }\n}\n\nclass SentryCloudflareTracer implements Tracer {\n public startSpan(name: string, options?: SpanOptions): Span {\n return startInactiveSpan({\n name,\n ...options,\n attributes: {\n ...options?.attributes,\n 'sentry.cloudflare_tracer': true,\n },\n });\n }\n\n /**\n * NOTE: This does not handle `context` being passed in. It will always put spans on the current scope.\n */\n public startActiveSpan<F extends (span: Span) => unknown>(name: string, fn: F): ReturnType<F>;\n public startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, fn: F): ReturnType<F>;\n public startActiveSpan<F extends (span: Span) => unknown>(\n name: string,\n options: SpanOptions,\n context: Context,\n fn: F,\n ): ReturnType<F>;\n public startActiveSpan<F extends (span: Span) => unknown>(\n name: string,\n options: unknown,\n context?: unknown,\n fn?: F,\n ): ReturnType<F> {\n const opts = (typeof options === 'object' && options !== null ? options : {}) as SpanOptions;\n\n const spanOpts = {\n name,\n ...opts,\n attributes: {\n ...opts.attributes,\n 'sentry.cloudflare_tracer': true,\n },\n };\n\n const callback = (\n typeof options === 'function'\n ? options\n : typeof context === 'function'\n ? context\n : typeof fn === 'function'\n ? fn\n : // eslint-disable-next-line @typescript-eslint/no-empty-function\n () => {}\n ) as F;\n\n // In OTEL the semantic matches `startSpanManual` because spans are not auto-ended\n return startSpanManual(spanOpts, callback) as ReturnType<F>;\n }\n}\n"],"names":[],"mappings":";;;AAIA;AACA;AACA;AACA;AACO,SAAS,wBAAwB,GAAS;AACjD,EAAE,KAAK,CAAC,uBAAuB,CAAC,IAAI,6BAA6B,EAAE,CAAC;AACpE;;AAEA,MAAM,+BAAwD,CAAA,WAAA,GAAA,EAAA,6BAAA,CAAA,SAAA,CAAA,MAAA,CAAA,IAAA,CAAA,IAAA,CAAA,CAAA;AAC9D,mBAAmB,QAAQ,GAAwB,IAAI,GAAG,GAAE;;AAE5D,GAAS,SAAS,CAAC,IAAI,EAAU,OAAO,EAAW,OAAO,EAAmC;AAC7F,IAAI,MAAM,GAAA,GAAM,CAAC,EAAA,IAAA,CAAA,CAAA,EAAA,OAAA,IAAA,EAAA,CAAA,CAAA,EAAA,OAAA,EAAA,SAAA,IAAA,EAAA,CAAA,CAAA;AACA,IAAA,IAAA,CAAA,IAAA,CAAA,QAAA,CAAA,GAAA,CAAA,GAAA,CAAA,EAAA;AACA,MAAA,IAAA,CAAA,QAAA,CAAA,GAAA,CAAA,GAAA,EAAA,IAAA,sBAAA,EAAA,CAAA;AACA;;AAEA;AACA,IAAA,OAAA,IAAA,CAAA,QAAA,CAAA,GAAA,CAAA,GAAA,CAAA;AACA;AACA;;AAEA,MAAA,sBAAA,EAAA;AACA,GAAA,SAAA,CAAA,IAAA,EAAA,OAAA,EAAA;AACA,IAAA,OAAA,iBAAA,CAAA;AACA,MAAA,IAAA;AACA,MAAA,GAAA,OAAA;AACA,MAAA,UAAA,EAAA;AACA,QAAA,GAAA,OAAA,EAAA,UAAA;AACA,QAAA,0BAAA,EAAA,IAAA;AACA,OAAA;AACA,KAAA,CAAA;AACA;;AAEA;AACA;AACA;;AASA,GAAA,eAAA;AACA,IAAA,IAAA;AACA,IAAA,OAAA;AACA,IAAA,OAAA;AACA,IAAA,EAAA;AACA,IAAA;AACA,IAAA,MAAA,IAAA,IAAA,OAAA,OAAA,KAAA,QAAA,IAAA,OAAA,KAAA,IAAA,GAAA,OAAA,GAAA,EAAA,CAAA;;AAEA,IAAA,MAAA,QAAA,GAAA;AACA,MAAA,IAAA;AACA,MAAA,GAAA,IAAA;AACA,MAAA,UAAA,EAAA;AACA,QAAA,GAAA,IAAA,CAAA,UAAA;AACA,QAAA,0BAAA,EAAA,IAAA;AACA,OAAA;AACA,KAAA;;AAEA,IAAA,MAAA,QAAA;AACA,MAAA,OAAA,OAAA,KAAA;AACA,UAAA;AACA,UAAA,OAAA,OAAA,KAAA;AACA,YAAA;AACA,YAAA,OAAA,EAAA,KAAA;AACA,cAAA;AACA;AACA,cAAA,MAAA;AACA,KAAA;;AAEA;AACA,IAAA,OAAA,eAAA,CAAA,QAAA,EAAA,QAAA,CAAA;AACA;AACA;;;;"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"9.
|
|
1
|
+
{"type":"module","version":"9.33.0","sideEffects":false}
|
|
@@ -42,7 +42,9 @@ function sentryPagesPlugin
|
|
|
42
42
|
setAsyncLocalStorageAsyncContextStrategy();
|
|
43
43
|
return context => {
|
|
44
44
|
const options = typeof handlerOrOptions === 'function' ? handlerOrOptions(context) : handlerOrOptions;
|
|
45
|
-
return wrapRequestHandler({ options, request: context.request, context }, () =>
|
|
45
|
+
return wrapRequestHandler({ options, request: context.request, context: { ...context, props: {} } }, () =>
|
|
46
|
+
context.next(),
|
|
47
|
+
);
|
|
46
48
|
};
|
|
47
49
|
}
|
|
48
50
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-plugin.js","sources":["../../src/pages-plugin.ts"],"sourcesContent":["import { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { wrapRequestHandler } from './request';\n\n/**\n * Plugin middleware for Cloudflare Pages.\n *\n * Initializes the SDK and wraps cloudflare pages requests with SDK instrumentation.\n *\n * @example Simple usage\n *\n * ```javascript\n * // functions/_middleware.js\n * import * as Sentry from '@sentry/cloudflare';\n *\n * export const onRequest = Sentry.sentryPagesPlugin({\n * dsn: process.env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * });\n * ```\n *\n * @example Usage with handler function to access context for environmental variables\n *\n * ```javascript\n * import * as Sentry from '@sentry/cloudflare';\n *\n * const const onRequest = Sentry.sentryPagesPlugin((context) => ({\n * dsn: context.env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * })\n * ```\n *\n * @param handlerOrOptions Configuration options or a function that returns configuration options.\n * @returns A plugin function that can be used in Cloudflare Pages.\n */\nexport function sentryPagesPlugin<\n Env = unknown,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Params extends string = any,\n Data extends Record<string, unknown> = Record<string, unknown>,\n // Although it is not ideal to use `any` here, it makes usage more flexible for different setups.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n PluginParams = any,\n>(\n handlerOrOptions:\n | CloudflareOptions\n | ((context: EventPluginContext<Env, Params, Data, PluginParams>) => CloudflareOptions),\n): PagesPluginFunction<Env, Params, Data, PluginParams> {\n setAsyncLocalStorageAsyncContextStrategy();\n return context => {\n const options = typeof handlerOrOptions === 'function' ? handlerOrOptions(context) : handlerOrOptions;\n return wrapRequestHandler({ options, request: context.request, context }, ()
|
|
1
|
+
{"version":3,"file":"pages-plugin.js","sources":["../../src/pages-plugin.ts"],"sourcesContent":["import { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { wrapRequestHandler } from './request';\n\n/**\n * Plugin middleware for Cloudflare Pages.\n *\n * Initializes the SDK and wraps cloudflare pages requests with SDK instrumentation.\n *\n * @example Simple usage\n *\n * ```javascript\n * // functions/_middleware.js\n * import * as Sentry from '@sentry/cloudflare';\n *\n * export const onRequest = Sentry.sentryPagesPlugin({\n * dsn: process.env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * });\n * ```\n *\n * @example Usage with handler function to access context for environmental variables\n *\n * ```javascript\n * import * as Sentry from '@sentry/cloudflare';\n *\n * const const onRequest = Sentry.sentryPagesPlugin((context) => ({\n * dsn: context.env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * })\n * ```\n *\n * @param handlerOrOptions Configuration options or a function that returns configuration options.\n * @returns A plugin function that can be used in Cloudflare Pages.\n */\nexport function sentryPagesPlugin<\n Env = unknown,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Params extends string = any,\n Data extends Record<string, unknown> = Record<string, unknown>,\n // Although it is not ideal to use `any` here, it makes usage more flexible for different setups.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n PluginParams = any,\n>(\n handlerOrOptions:\n | CloudflareOptions\n | ((context: EventPluginContext<Env, Params, Data, PluginParams>) => CloudflareOptions),\n): PagesPluginFunction<Env, Params, Data, PluginParams> {\n setAsyncLocalStorageAsyncContextStrategy();\n return context => {\n const options = typeof handlerOrOptions === 'function' ? handlerOrOptions(context) : handlerOrOptions;\n return wrapRequestHandler({ options, request: context.request, context: { ...context, props: {} } }, () =>\n context.next(),\n );\n };\n}\n"],"names":[],"mappings":";;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS;;AAQhB;AACA,EAAE;;AAEE;AACJ,EAAwD;AACxD,EAAE,wCAAwC,EAAE;AAC5C,EAAE,OAAO,WAAW;AACpB,IAAI,MAAM,OAAA,GAAU,OAAO,gBAAiB,KAAI,UAAW,GAAE,gBAAgB,CAAC,OAAO,CAAA,GAAI,gBAAgB;AACzG,IAAI,OAAO,kBAAkB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,EAAC,EAAI,EAAC,EAAE;AACzG,MAAM,OAAO,CAAC,IAAI,EAAE;AACpB,KAAK;AACL,GAAG;AACH;;;;"}
|
package/build/esm/request.js
CHANGED
|
@@ -17,7 +17,9 @@ function wrapRequestHandler(
|
|
|
17
17
|
// see: https://github.com/getsentry/sentry-javascript/issues/13217
|
|
18
18
|
const context = wrapperOptions.context ;
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const waitUntil = context?.waitUntil?.bind?.(context);
|
|
21
|
+
|
|
22
|
+
const client = init({ ...options, ctx: context });
|
|
21
23
|
isolationScope.setClient(client);
|
|
22
24
|
|
|
23
25
|
const urlObject = parseStringToURLObject(request.url);
|
|
@@ -47,7 +49,7 @@ function wrapRequestHandler(
|
|
|
47
49
|
captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });
|
|
48
50
|
throw e;
|
|
49
51
|
} finally {
|
|
50
|
-
|
|
52
|
+
waitUntil?.(flush(2000));
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -71,7 +73,7 @@ function wrapRequestHandler(
|
|
|
71
73
|
captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });
|
|
72
74
|
throw e;
|
|
73
75
|
} finally {
|
|
74
|
-
|
|
76
|
+
waitUntil?.(flush(2000));
|
|
75
77
|
}
|
|
76
78
|
},
|
|
77
79
|
);
|
package/build/esm/request.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sources":["../../src/request.ts"],"sourcesContent":["import type { ExecutionContext, IncomingRequestCfProperties } from '@cloudflare/workers-types';\nimport {\n captureException,\n continueTrace,\n flush,\n getHttpSpanDetailsFromUrlObject,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n setHttpStatus,\n startSpan,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { addCloudResourceContext, addCultureContext, addRequest } from './scope-utils';\nimport { init } from './sdk';\n\ninterface RequestHandlerWrapperOptions {\n options: CloudflareOptions;\n request: Request<unknown, IncomingRequestCfProperties<unknown>>;\n context: ExecutionContext;\n}\n\n/**\n * Wraps a cloudflare request handler in Sentry instrumentation\n */\nexport function wrapRequestHandler(\n wrapperOptions: RequestHandlerWrapperOptions,\n handler: (...args: unknown[]) => Response | Promise<Response>,\n): Promise<Response> {\n return withIsolationScope(async isolationScope => {\n const { options, request } = wrapperOptions;\n\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context = wrapperOptions.context as ExecutionContext | undefined;\n\n const client = init(options);\n isolationScope.setClient(client);\n\n const urlObject = parseStringToURLObject(request.url);\n const [name, attributes] = getHttpSpanDetailsFromUrlObject(urlObject, 'server', 'auto.http.cloudflare', request);\n\n const contentLength = request.headers.get('content-length');\n if (contentLength) {\n attributes['http.request.body.size'] = parseInt(contentLength, 10);\n }\n\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] = 'http.server';\n\n addCloudResourceContext(isolationScope);\n if (request) {\n addRequest(isolationScope, request);\n if (request.cf) {\n addCultureContext(isolationScope, request.cf);\n attributes['network.protocol.name'] = request.cf.httpProtocol;\n }\n }\n\n // Do not capture spans for OPTIONS and HEAD requests\n if (request.method === 'OPTIONS' || request.method === 'HEAD') {\n try {\n return await handler();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });\n throw e;\n } finally {\n
|
|
1
|
+
{"version":3,"file":"request.js","sources":["../../src/request.ts"],"sourcesContent":["import type { ExecutionContext, IncomingRequestCfProperties } from '@cloudflare/workers-types';\nimport {\n captureException,\n continueTrace,\n flush,\n getHttpSpanDetailsFromUrlObject,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n setHttpStatus,\n startSpan,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { addCloudResourceContext, addCultureContext, addRequest } from './scope-utils';\nimport { init } from './sdk';\n\ninterface RequestHandlerWrapperOptions {\n options: CloudflareOptions;\n request: Request<unknown, IncomingRequestCfProperties<unknown>>;\n context: ExecutionContext;\n}\n\n/**\n * Wraps a cloudflare request handler in Sentry instrumentation\n */\nexport function wrapRequestHandler(\n wrapperOptions: RequestHandlerWrapperOptions,\n handler: (...args: unknown[]) => Response | Promise<Response>,\n): Promise<Response> {\n return withIsolationScope(async isolationScope => {\n const { options, request } = wrapperOptions;\n\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context = wrapperOptions.context as ExecutionContext | undefined;\n\n const waitUntil = context?.waitUntil?.bind?.(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n const urlObject = parseStringToURLObject(request.url);\n const [name, attributes] = getHttpSpanDetailsFromUrlObject(urlObject, 'server', 'auto.http.cloudflare', request);\n\n const contentLength = request.headers.get('content-length');\n if (contentLength) {\n attributes['http.request.body.size'] = parseInt(contentLength, 10);\n }\n\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] = 'http.server';\n\n addCloudResourceContext(isolationScope);\n if (request) {\n addRequest(isolationScope, request);\n if (request.cf) {\n addCultureContext(isolationScope, request.cf);\n attributes['network.protocol.name'] = request.cf.httpProtocol;\n }\n }\n\n // Do not capture spans for OPTIONS and HEAD requests\n if (request.method === 'OPTIONS' || request.method === 'HEAD') {\n try {\n return await handler();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });\n throw e;\n } finally {\n waitUntil?.(flush(2000));\n }\n }\n\n return continueTrace(\n { sentryTrace: request.headers.get('sentry-trace') || '', baggage: request.headers.get('baggage') },\n () => {\n // Note: This span will not have a duration unless I/O happens in the handler. This is\n // because of how the cloudflare workers runtime works.\n // See: https://developers.cloudflare.com/workers/runtime-apis/performance/\n return startSpan(\n {\n name,\n attributes,\n },\n async span => {\n try {\n const res = await handler();\n setHttpStatus(span, res.status);\n return res;\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });\n throw e;\n } finally {\n waitUntil?.(flush(2000));\n }\n },\n );\n },\n );\n });\n}\n"],"names":[],"mappings":"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"}
|
package/build/esm/sdk.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { dedupeIntegration, inboundFiltersIntegration, functionToStringIntegration, linkedErrorsIntegration, requestDataIntegration, consoleIntegration, getIntegrationsToSetup, stackParserFromStackParserOptions, initAndBind } from '@sentry/core';
|
|
2
2
|
import { CloudflareClient } from './client.js';
|
|
3
|
+
import { makeFlushLock } from './flush.js';
|
|
3
4
|
import { fetchIntegration } from './integrations/fetch.js';
|
|
5
|
+
import { setupOpenTelemetryTracer } from './opentelemetry/tracer.js';
|
|
4
6
|
import { makeCloudflareTransport } from './transport.js';
|
|
5
7
|
import { defaultStackParser } from './vendor/stacktrace.js';
|
|
6
8
|
|
|
@@ -8,7 +10,9 @@ import { defaultStackParser } from './vendor/stacktrace.js';
|
|
|
8
10
|
function getDefaultIntegrations(options) {
|
|
9
11
|
const sendDefaultPii = options.sendDefaultPii ?? false;
|
|
10
12
|
return [
|
|
11
|
-
|
|
13
|
+
// The Dedupe integration should not be used in workflows because we want to
|
|
14
|
+
// capture all step failures, even if they are the same error.
|
|
15
|
+
...(options.enableDedupe === false ? [] : [dedupeIntegration()]),
|
|
12
16
|
// TODO(v10): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`
|
|
13
17
|
// eslint-disable-next-line deprecation/deprecation
|
|
14
18
|
inboundFiltersIntegration(),
|
|
@@ -29,13 +33,28 @@ function init(options) {
|
|
|
29
33
|
options.defaultIntegrations = getDefaultIntegrations(options);
|
|
30
34
|
}
|
|
31
35
|
|
|
36
|
+
const flushLock = options.ctx ? makeFlushLock(options.ctx) : undefined;
|
|
37
|
+
delete options.ctx;
|
|
38
|
+
|
|
32
39
|
const clientOptions = {
|
|
33
40
|
...options,
|
|
34
41
|
stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),
|
|
35
42
|
integrations: getIntegrationsToSetup(options),
|
|
36
43
|
transport: options.transport || makeCloudflareTransport,
|
|
44
|
+
flushLock,
|
|
37
45
|
};
|
|
38
46
|
|
|
47
|
+
/**
|
|
48
|
+
* The Cloudflare SDK is not OpenTelemetry native, however, we set up some OpenTelemetry compatibility
|
|
49
|
+
* via a custom trace provider.
|
|
50
|
+
* This ensures that any spans emitted via `@opentelemetry/api` will be captured by Sentry.
|
|
51
|
+
* HOWEVER, big caveat: This does not handle custom context handling, it will always work off the current scope.
|
|
52
|
+
* This should be good enough for many, but not all integrations.
|
|
53
|
+
*/
|
|
54
|
+
if (!options.skipOpenTelemetrySetup) {
|
|
55
|
+
setupOpenTelemetryTracer();
|
|
56
|
+
}
|
|
57
|
+
|
|
39
58
|
return initAndBind(CloudflareClient, clientOptions) ;
|
|
40
59
|
}
|
|
41
60
|
|
package/build/esm/sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.js","sources":["../../src/sdk.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport {\n consoleIntegration,\n dedupeIntegration,\n functionToStringIntegration,\n getIntegrationsToSetup,\n inboundFiltersIntegration,\n initAndBind,\n linkedErrorsIntegration,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport type { CloudflareClientOptions, CloudflareOptions } from './client';\nimport { CloudflareClient } from './client';\nimport { fetchIntegration } from './integrations/fetch';\nimport { makeCloudflareTransport } from './transport';\nimport { defaultStackParser } from './vendor/stacktrace';\n\n/** Get the default integrations for the Cloudflare SDK. */\nexport function getDefaultIntegrations(options: CloudflareOptions): Integration[] {\n const sendDefaultPii = options.sendDefaultPii ?? false;\n return [\n dedupeIntegration(),\n // TODO(v10): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`\n // eslint-disable-next-line deprecation/deprecation\n inboundFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n fetchIntegration(),\n // TODO(v10): the `include` object should be defined directly in the integration based on `sendDefaultPii`\n requestDataIntegration(sendDefaultPii ? undefined : { include: { cookies: false } }),\n consoleIntegration(),\n ];\n}\n\n/**\n * Initializes the cloudflare SDK.\n */\nexport function init(options: CloudflareOptions): CloudflareClient | undefined {\n if (options.defaultIntegrations === undefined) {\n options.defaultIntegrations = getDefaultIntegrations(options);\n }\n\n const clientOptions: CloudflareClientOptions = {\n ...options,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n integrations: getIntegrationsToSetup(options),\n transport: options.transport || makeCloudflareTransport,\n };\n\n return initAndBind(CloudflareClient, clientOptions) as CloudflareClient;\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sdk.js","sources":["../../src/sdk.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport {\n consoleIntegration,\n dedupeIntegration,\n functionToStringIntegration,\n getIntegrationsToSetup,\n inboundFiltersIntegration,\n initAndBind,\n linkedErrorsIntegration,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport type { CloudflareClientOptions, CloudflareOptions } from './client';\nimport { CloudflareClient } from './client';\nimport { makeFlushLock } from './flush';\nimport { fetchIntegration } from './integrations/fetch';\nimport { setupOpenTelemetryTracer } from './opentelemetry/tracer';\nimport { makeCloudflareTransport } from './transport';\nimport { defaultStackParser } from './vendor/stacktrace';\n\n/** Get the default integrations for the Cloudflare SDK. */\nexport function getDefaultIntegrations(options: CloudflareOptions): Integration[] {\n const sendDefaultPii = options.sendDefaultPii ?? false;\n return [\n // The Dedupe integration should not be used in workflows because we want to\n // capture all step failures, even if they are the same error.\n ...(options.enableDedupe === false ? [] : [dedupeIntegration()]),\n // TODO(v10): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`\n // eslint-disable-next-line deprecation/deprecation\n inboundFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n fetchIntegration(),\n // TODO(v10): the `include` object should be defined directly in the integration based on `sendDefaultPii`\n requestDataIntegration(sendDefaultPii ? undefined : { include: { cookies: false } }),\n consoleIntegration(),\n ];\n}\n\n/**\n * Initializes the cloudflare SDK.\n */\nexport function init(options: CloudflareOptions): CloudflareClient | undefined {\n if (options.defaultIntegrations === undefined) {\n options.defaultIntegrations = getDefaultIntegrations(options);\n }\n\n const flushLock = options.ctx ? makeFlushLock(options.ctx) : undefined;\n delete options.ctx;\n\n const clientOptions: CloudflareClientOptions = {\n ...options,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n integrations: getIntegrationsToSetup(options),\n transport: options.transport || makeCloudflareTransport,\n flushLock,\n };\n\n /**\n * The Cloudflare SDK is not OpenTelemetry native, however, we set up some OpenTelemetry compatibility\n * via a custom trace provider.\n * This ensures that any spans emitted via `@opentelemetry/api` will be captured by Sentry.\n * HOWEVER, big caveat: This does not handle custom context handling, it will always work off the current scope.\n * This should be good enough for many, but not all integrations.\n */\n if (!options.skipOpenTelemetrySetup) {\n setupOpenTelemetryTracer();\n }\n\n return initAndBind(CloudflareClient, clientOptions) as CloudflareClient;\n}\n"],"names":[],"mappings":";;;;;;;;AAoBA;AACO,SAAS,sBAAsB,CAAC,OAAO,EAAoC;AAClF,EAAE,MAAM,cAAe,GAAE,OAAO,CAAC,cAAA,IAAkB,KAAK;AACxD,EAAE,OAAO;AACT;AACA;AACA,IAAI,IAAI,OAAO,CAAC,YAAA,KAAiB,KAAM,GAAE,EAAC,GAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACpE;AACA;AACA,IAAI,yBAAyB,EAAE;AAC/B,IAAI,2BAA2B,EAAE;AACjC,IAAI,uBAAuB,EAAE;AAC7B,IAAI,gBAAgB,EAAE;AACtB;AACA,IAAI,sBAAsB,CAAC,cAAe,GAAE,YAAY,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,KAAM,EAAA,EAAG,CAAC;AACxF,IAAI,kBAAkB,EAAE;AACxB,GAAG;AACH;;AAEA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAmD;AAC/E,EAAE,IAAI,OAAO,CAAC,mBAAoB,KAAI,SAAS,EAAE;AACjD,IAAI,OAAO,CAAC,mBAAA,GAAsB,sBAAsB,CAAC,OAAO,CAAC;AACjE;;AAEA,EAAE,MAAM,SAAA,GAAY,OAAO,CAAC,GAAI,GAAE,aAAa,CAAC,OAAO,CAAC,GAAG,CAAA,GAAI,SAAS;AACxE,EAAE,OAAO,OAAO,CAAC,GAAG;;AAEpB,EAAE,MAAM,aAAa,GAA4B;AACjD,IAAI,GAAG,OAAO;AACd,IAAI,WAAW,EAAE,iCAAiC,CAAC,OAAO,CAAC,WAAA,IAAe,kBAAkB,CAAC;AAC7F,IAAI,YAAY,EAAE,sBAAsB,CAAC,OAAO,CAAC;AACjD,IAAI,SAAS,EAAE,OAAO,CAAC,SAAA,IAAa,uBAAuB;AAC3D,IAAI,SAAS;AACb,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE;AACvC,IAAI,wBAAwB,EAAE;AAC9B;;AAEA,EAAE,OAAO,WAAW,CAAC,gBAAgB,EAAE,aAAa,CAAE;AACtD;;;;"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { withIsolationScope, withScope, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, captureException, flush } from '@sentry/core';
|
|
2
|
+
import { setAsyncLocalStorageAsyncContextStrategy } from './async.js';
|
|
3
|
+
import { addCloudResourceContext } from './scope-utils.js';
|
|
4
|
+
import { init } from './sdk.js';
|
|
5
|
+
|
|
6
|
+
const UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i;
|
|
7
|
+
|
|
8
|
+
function propagationContextFromInstanceId(instanceId) {
|
|
9
|
+
// Validate and normalize traceId - should be a valid UUID with or without hyphens
|
|
10
|
+
if (!UUID_REGEX.test(instanceId)) {
|
|
11
|
+
throw new Error("Invalid 'instanceId' for workflow: Sentry requires random UUIDs for instanceId.");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Remove hyphens to get UUID without hyphens
|
|
15
|
+
const traceId = instanceId.replace(/-/g, '');
|
|
16
|
+
|
|
17
|
+
// Derive sampleRand from last 4 characters of the random UUID
|
|
18
|
+
//
|
|
19
|
+
// We cannot store any state between workflow steps, so we derive the
|
|
20
|
+
// sampleRand from the traceId itself. This ensures that the sampling is
|
|
21
|
+
// consistent across all steps in the same workflow instance.
|
|
22
|
+
const sampleRand = parseInt(traceId.slice(-4), 16) / 0xffff;
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
traceId,
|
|
26
|
+
sampleRand,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function workflowStepWithSentry(
|
|
31
|
+
instanceId,
|
|
32
|
+
options,
|
|
33
|
+
callback,
|
|
34
|
+
) {
|
|
35
|
+
setAsyncLocalStorageAsyncContextStrategy();
|
|
36
|
+
|
|
37
|
+
return withIsolationScope(async isolationScope => {
|
|
38
|
+
const client = init({ ...options, enableDedupe: false });
|
|
39
|
+
isolationScope.setClient(client);
|
|
40
|
+
|
|
41
|
+
addCloudResourceContext(isolationScope);
|
|
42
|
+
|
|
43
|
+
return withScope(async scope => {
|
|
44
|
+
const propagationContext = propagationContextFromInstanceId(instanceId);
|
|
45
|
+
scope.setPropagationContext(propagationContext);
|
|
46
|
+
|
|
47
|
+
// eslint-disable-next-line no-return-await
|
|
48
|
+
return await callback();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class WrappedWorkflowStep {
|
|
54
|
+
constructor(
|
|
55
|
+
_instanceId,
|
|
56
|
+
_ctx,
|
|
57
|
+
_options,
|
|
58
|
+
_step,
|
|
59
|
+
) {this._instanceId = _instanceId;this._ctx = _ctx;this._options = _options;this._step = _step;}
|
|
60
|
+
|
|
61
|
+
async do(
|
|
62
|
+
name,
|
|
63
|
+
configOrCallback,
|
|
64
|
+
maybeCallback,
|
|
65
|
+
) {
|
|
66
|
+
const userCallback = (maybeCallback || configOrCallback) ;
|
|
67
|
+
const config = typeof configOrCallback === 'function' ? undefined : configOrCallback;
|
|
68
|
+
|
|
69
|
+
const instrumentedCallback = async () => {
|
|
70
|
+
return workflowStepWithSentry(this._instanceId, this._options, async () => {
|
|
71
|
+
return startSpan(
|
|
72
|
+
{
|
|
73
|
+
op: 'function.step.do',
|
|
74
|
+
name,
|
|
75
|
+
attributes: {
|
|
76
|
+
'cloudflare.workflow.timeout': config?.timeout,
|
|
77
|
+
'cloudflare.workflow.retries.backoff': config?.retries?.backoff,
|
|
78
|
+
'cloudflare.workflow.retries.delay': config?.retries?.delay,
|
|
79
|
+
'cloudflare.workflow.retries.limit': config?.retries?.limit,
|
|
80
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',
|
|
81
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
async span => {
|
|
85
|
+
try {
|
|
86
|
+
const result = await userCallback();
|
|
87
|
+
span.setStatus({ code: 1 });
|
|
88
|
+
return result;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
captureException(error, { mechanism: { handled: true, type: 'cloudflare' } });
|
|
91
|
+
throw error;
|
|
92
|
+
} finally {
|
|
93
|
+
this._ctx.waitUntil(flush(2000));
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return config ? this._step.do(name, config, instrumentedCallback) : this._step.do(name, instrumentedCallback);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async sleep(name, duration) {
|
|
104
|
+
return this._step.sleep(name, duration);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async sleepUntil(name, timestamp) {
|
|
108
|
+
return this._step.sleepUntil(name, timestamp);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async waitForEvent(
|
|
112
|
+
name,
|
|
113
|
+
options,
|
|
114
|
+
) {
|
|
115
|
+
return this._step.waitForEvent(name, options);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Instruments a Cloudflare Workflow class with Sentry.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const InstrumentedWorkflow = instrumentWorkflowWithSentry(
|
|
125
|
+
* (env) => ({ dsn: env.SENTRY_DSN }),
|
|
126
|
+
* MyWorkflowClass
|
|
127
|
+
* );
|
|
128
|
+
*
|
|
129
|
+
* export default InstrumentedWorkflow;
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @param optionsCallback - Function that returns Sentry options to initialize Sentry
|
|
133
|
+
* @param WorkflowClass - The workflow class to instrument
|
|
134
|
+
* @returns Instrumented workflow class with the same interface
|
|
135
|
+
*/
|
|
136
|
+
function instrumentWorkflowWithSentry
|
|
137
|
+
|
|
138
|
+
(optionsCallback, WorkFlowClass) {
|
|
139
|
+
return new Proxy(WorkFlowClass, {
|
|
140
|
+
construct(target, args, newTarget) {
|
|
141
|
+
const [ctx, env] = args;
|
|
142
|
+
const options = optionsCallback(env);
|
|
143
|
+
const instance = Reflect.construct(target, args, newTarget) ;
|
|
144
|
+
return new Proxy(instance, {
|
|
145
|
+
get(obj, prop, receiver) {
|
|
146
|
+
if (prop === 'run') {
|
|
147
|
+
return async function (event, step) {
|
|
148
|
+
return obj.run.call(obj, event, new WrappedWorkflowStep(event.instanceId, ctx, options, step));
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return Reflect.get(obj, prop, receiver);
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
},
|
|
155
|
+
}) ;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { instrumentWorkflowWithSentry };
|
|
159
|
+
//# sourceMappingURL=workflows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflows.js","sources":["../../src/workflows.ts"],"sourcesContent":["import type { PropagationContext } from '@sentry/core';\nimport {\n captureException,\n flush,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type {\n WorkflowEntrypoint,\n WorkflowEvent,\n WorkflowSleepDuration,\n WorkflowStep,\n WorkflowStepConfig,\n WorkflowStepEvent,\n WorkflowTimeoutDuration,\n} from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { addCloudResourceContext } from './scope-utils';\nimport { init } from './sdk';\n\nconst UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i;\n\nfunction propagationContextFromInstanceId(instanceId: string): PropagationContext {\n // Validate and normalize traceId - should be a valid UUID with or without hyphens\n if (!UUID_REGEX.test(instanceId)) {\n throw new Error(\"Invalid 'instanceId' for workflow: Sentry requires random UUIDs for instanceId.\");\n }\n\n // Remove hyphens to get UUID without hyphens\n const traceId = instanceId.replace(/-/g, '');\n\n // Derive sampleRand from last 4 characters of the random UUID\n //\n // We cannot store any state between workflow steps, so we derive the\n // sampleRand from the traceId itself. This ensures that the sampling is\n // consistent across all steps in the same workflow instance.\n const sampleRand = parseInt(traceId.slice(-4), 16) / 0xffff;\n\n return {\n traceId,\n sampleRand,\n };\n}\n\nasync function workflowStepWithSentry<V>(\n instanceId: string,\n options: CloudflareOptions,\n callback: () => V,\n): Promise<V> {\n setAsyncLocalStorageAsyncContextStrategy();\n\n return withIsolationScope(async isolationScope => {\n const client = init({ ...options, enableDedupe: false });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return withScope(async scope => {\n const propagationContext = propagationContextFromInstanceId(instanceId);\n scope.setPropagationContext(propagationContext);\n\n // eslint-disable-next-line no-return-await\n return await callback();\n });\n });\n}\n\nclass WrappedWorkflowStep implements WorkflowStep {\n public constructor(\n private _instanceId: string,\n private _ctx: ExecutionContext,\n private _options: CloudflareOptions,\n private _step: WorkflowStep,\n ) {}\n\n public async do<T extends Rpc.Serializable<T>>(name: string, callback: () => Promise<T>): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n config: WorkflowStepConfig,\n callback: () => Promise<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n configOrCallback: WorkflowStepConfig | (() => Promise<T>),\n maybeCallback?: () => Promise<T>,\n ): Promise<T> {\n const userCallback = (maybeCallback || configOrCallback) as () => Promise<T>;\n const config = typeof configOrCallback === 'function' ? undefined : configOrCallback;\n\n const instrumentedCallback: () => Promise<T> = async () => {\n return workflowStepWithSentry(this._instanceId, this._options, async () => {\n return startSpan(\n {\n op: 'function.step.do',\n name,\n attributes: {\n 'cloudflare.workflow.timeout': config?.timeout,\n 'cloudflare.workflow.retries.backoff': config?.retries?.backoff,\n 'cloudflare.workflow.retries.delay': config?.retries?.delay,\n 'cloudflare.workflow.retries.limit': config?.retries?.limit,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async span => {\n try {\n const result = await userCallback();\n span.setStatus({ code: 1 });\n return result;\n } catch (error) {\n captureException(error, { mechanism: { handled: true, type: 'cloudflare' } });\n throw error;\n } finally {\n this._ctx.waitUntil(flush(2000));\n }\n },\n );\n });\n };\n\n return config ? this._step.do(name, config, instrumentedCallback) : this._step.do(name, instrumentedCallback);\n }\n\n public async sleep(name: string, duration: WorkflowSleepDuration): Promise<void> {\n return this._step.sleep(name, duration);\n }\n\n public async sleepUntil(name: string, timestamp: Date | number): Promise<void> {\n return this._step.sleepUntil(name, timestamp);\n }\n\n public async waitForEvent<T extends Rpc.Serializable<T>>(\n name: string,\n options: { type: string; timeout?: WorkflowTimeoutDuration | number },\n ): Promise<WorkflowStepEvent<T>> {\n return this._step.waitForEvent<T>(name, options);\n }\n}\n\n/**\n * Instruments a Cloudflare Workflow class with Sentry.\n *\n * @example\n * ```typescript\n * const InstrumentedWorkflow = instrumentWorkflowWithSentry(\n * (env) => ({ dsn: env.SENTRY_DSN }),\n * MyWorkflowClass\n * );\n *\n * export default InstrumentedWorkflow;\n * ```\n *\n * @param optionsCallback - Function that returns Sentry options to initialize Sentry\n * @param WorkflowClass - The workflow class to instrument\n * @returns Instrumented workflow class with the same interface\n */\nexport function instrumentWorkflowWithSentry<\n E, // Environment type\n P, // Payload type\n T extends WorkflowEntrypoint<E, P>, // WorkflowEntrypoint type\n C extends new (ctx: ExecutionContext, env: E) => T, // Constructor type of the WorkflowEntrypoint class\n>(optionsCallback: (env: E) => CloudflareOptions, WorkFlowClass: C): C {\n return new Proxy(WorkFlowClass, {\n construct(target: C, args: [ctx: ExecutionContext, env: E], newTarget) {\n const [ctx, env] = args;\n const options = optionsCallback(env);\n const instance = Reflect.construct(target, args, newTarget) as T;\n return new Proxy(instance, {\n get(obj, prop, receiver) {\n if (prop === 'run') {\n return async function (event: WorkflowEvent<P>, step: WorkflowStep): Promise<unknown> {\n return obj.run.call(obj, event, new WrappedWorkflowStep(event.instanceId, ctx, options, step));\n };\n }\n return Reflect.get(obj, prop, receiver);\n },\n });\n },\n }) as C;\n}\n"],"names":[],"mappings":"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"}
|
package/build/types/client.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
1
2
|
import type { ClientOptions, Options } from '@sentry/core';
|
|
2
3
|
import { ServerRuntimeClient } from '@sentry/core';
|
|
4
|
+
import type { makeFlushLock } from './flush';
|
|
3
5
|
import type { CloudflareTransportOptions } from './transport';
|
|
4
6
|
/**
|
|
5
7
|
* The Sentry Cloudflare SDK Client.
|
|
@@ -7,14 +9,41 @@ import type { CloudflareTransportOptions } from './transport';
|
|
|
7
9
|
* @see CloudflareClientOptions for documentation on configuration options.
|
|
8
10
|
* @see ServerRuntimeClient for usage documentation.
|
|
9
11
|
*/
|
|
10
|
-
export declare class CloudflareClient extends ServerRuntimeClient
|
|
12
|
+
export declare class CloudflareClient extends ServerRuntimeClient {
|
|
13
|
+
private readonly _flushLock;
|
|
11
14
|
/**
|
|
12
15
|
* Creates a new Cloudflare SDK instance.
|
|
13
16
|
* @param options Configuration options for this SDK.
|
|
14
17
|
*/
|
|
15
18
|
constructor(options: CloudflareClientOptions);
|
|
19
|
+
/**
|
|
20
|
+
* Flushes pending operations and ensures all data is processed.
|
|
21
|
+
* If a timeout is provided, the operation will be completed within the specified time limit.
|
|
22
|
+
*
|
|
23
|
+
* @param {number} [timeout] - Optional timeout in milliseconds to force the completion of the flush operation.
|
|
24
|
+
* @return {Promise<boolean>} A promise that resolves to a boolean indicating whether the flush operation was successful.
|
|
25
|
+
*/
|
|
26
|
+
flush(timeout?: number): Promise<boolean>;
|
|
16
27
|
}
|
|
17
28
|
interface BaseCloudflareOptions {
|
|
29
|
+
/**
|
|
30
|
+
* @ignore Used internally to disable the deDupeIntegration for workflows.
|
|
31
|
+
* @hidden Used internally to disable the deDupeIntegration for workflows.
|
|
32
|
+
* @default true
|
|
33
|
+
*/
|
|
34
|
+
enableDedupe?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* The Cloudflare SDK is not OpenTelemetry native, however, we set up some OpenTelemetry compatibility
|
|
37
|
+
* via a custom trace provider.
|
|
38
|
+
* This ensures that any spans emitted via `@opentelemetry/api` will be captured by Sentry.
|
|
39
|
+
* HOWEVER, big caveat: This does not handle custom context handling, it will always work off the current scope.
|
|
40
|
+
* This should be good enough for many, but not all integrations.
|
|
41
|
+
*
|
|
42
|
+
* If you want to opt-out of setting up the OpenTelemetry compatibility tracer, set this to `true`.
|
|
43
|
+
*
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
skipOpenTelemetrySetup?: boolean;
|
|
18
47
|
}
|
|
19
48
|
/**
|
|
20
49
|
* Configuration options for the Sentry Cloudflare SDK
|
|
@@ -22,6 +51,7 @@ interface BaseCloudflareOptions {
|
|
|
22
51
|
* @see @sentry/core Options for more information.
|
|
23
52
|
*/
|
|
24
53
|
export interface CloudflareOptions extends Options<CloudflareTransportOptions>, BaseCloudflareOptions {
|
|
54
|
+
ctx?: ExecutionContext;
|
|
25
55
|
}
|
|
26
56
|
/**
|
|
27
57
|
* Configuration options for the Sentry Cloudflare SDK Client class
|
|
@@ -29,6 +59,7 @@ export interface CloudflareOptions extends Options<CloudflareTransportOptions>,
|
|
|
29
59
|
* @see CloudflareClient for more information.
|
|
30
60
|
*/
|
|
31
61
|
export interface CloudflareClientOptions extends ClientOptions<CloudflareTransportOptions>, BaseCloudflareOptions {
|
|
62
|
+
flushLock?: ReturnType<typeof makeFlushLock>;
|
|
32
63
|
}
|
|
33
64
|
export {};
|
|
34
65
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAA8B,MAAM,cAAc,CAAC;AACvF,OAAO,EAAoB,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAA8B,MAAM,cAAc,CAAC;AACvF,OAAO,EAAoB,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,mBAAmB;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IAErE;;;OAGG;gBACgB,OAAO,EAAE,uBAAuB;IAiBnD;;;;;;OAMG;IACU,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAMvD;AAED,UAAU,qBAAqB;IAC7B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO,CAAC,0BAA0B,CAAC,EAAE,qBAAqB;IACnG,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAwB,SAAQ,aAAa,CAAC,0BAA0B,CAAC,EAAE,qBAAqB;IAC/G,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;CAC9C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durableobject.d.ts","sourceRoot":"","sources":["../../src/durableobject.ts"],"names":[],"mappings":";AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"durableobject.d.ts","sourceRoot":"","sources":["../../src/durableobject.ts"],"names":[],"mappings":";AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AA2FlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,iCAAiC,CAC/C,CAAC,EACD,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC1B,CAAC,SAAS,KAAK,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EACtD,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,CAAC,GAAG,CAAC,CAsF1E"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ExecutionContext } from '@cloudflare/workers-types';
|
|
2
|
+
type FlushLock = {
|
|
3
|
+
readonly ready: Promise<void>;
|
|
4
|
+
readonly finalize: () => Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Enhances the given execution context by wrapping its `waitUntil` method with a proxy
|
|
8
|
+
* to monitor pending tasks, and provides a flusher function to ensure all tasks
|
|
9
|
+
* have been completed before executing any subsequent logic.
|
|
10
|
+
*
|
|
11
|
+
* @param {ExecutionContext} context - The execution context to be enhanced. If no context is provided, the function returns undefined.
|
|
12
|
+
* @return {FlushLock} Returns a flusher function if a valid context is provided, otherwise undefined.
|
|
13
|
+
*/
|
|
14
|
+
export declare function makeFlushLock(context: ExecutionContext): FlushLock;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=flush.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flush.d.ts","sourceRoot":"","sources":["../../src/flush.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,KAAK,SAAS,GAAG;IACf,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAsBlE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/handler.ts"],"names":[],"mappings":";AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAOlD;;;;;;;;;;GAUG;AAEH,wBAAgB,UAAU,CAAC,GAAG,GAAG,OAAO,EAAE,mBAAmB,GAAG,OAAO,EAAE,cAAc,GAAG,OAAO,EAC/F,eAAe,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,iBAAiB,EAChD,OAAO,EAAE,eAAe,CAAC,GAAG,EAAE,mBAAmB,EAAE,cAAc,CAAC,GACjE,eAAe,CAAC,GAAG,EAAE,mBAAmB,EAAE,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/handler.ts"],"names":[],"mappings":";AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAOlD;;;;;;;;;;GAUG;AAEH,wBAAgB,UAAU,CAAC,GAAG,GAAG,OAAO,EAAE,mBAAmB,GAAG,OAAO,EAAE,cAAc,GAAG,OAAO,EAC/F,eAAe,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,iBAAiB,EAChD,OAAO,EAAE,eAAe,CAAC,GAAG,EAAE,mBAAmB,EAAE,cAAc,CAAC,GACjE,eAAe,CAAC,GAAG,EAAE,mBAAmB,EAAE,cAAc,CAAC,CA6M3D"}
|
package/build/types/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export { wrapRequestHandler } from './request';
|
|
|
9
9
|
export { CloudflareClient } from './client';
|
|
10
10
|
export { getDefaultIntegrations } from './sdk';
|
|
11
11
|
export { fetchIntegration } from './integrations/fetch';
|
|
12
|
+
export { vercelAIIntegration } from './integrations/tracing/vercelai';
|
|
12
13
|
export { instrumentD1WithSentry } from './d1';
|
|
14
|
+
export { instrumentWorkflowWithSentry } from './workflows';
|
|
13
15
|
export { setAsyncLocalStorageAsyncContextStrategy } from './async';
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,OAAO,EACP,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,uBAAuB,EACvB,OAAO,EACP,aAAa,EACb,IAAI,EACJ,UAAU,EACV,UAAU,EACV,MAAM,EACN,IAAI,GACL,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,KAAK,EACL,eAAe,EACf,WAAW,EACX,KAAK,EACL,SAAS,EACT,aAAa,EACb,SAAS,EACT,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,EACL,WAAW,EACX,UAAU,EACV,QAAQ,EACR,SAAS,EACT,MAAM,EACN,OAAO,EACP,OAAO,EACP,yBAAyB,EACzB,aAAa,EACb,SAAS,EACT,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,2BAA2B,EAE3B,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,EACjB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,4BAA4B,EAC5B,gCAAgC,EAChC,gCAAgC,EAChC,qCAAqC,EACrC,cAAc,EACd,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iCAAiC,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,OAAO,EACP,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,uBAAuB,EACvB,OAAO,EACP,aAAa,EACb,IAAI,EACJ,UAAU,EACV,UAAU,EACV,MAAM,EACN,IAAI,GACL,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,KAAK,EACL,eAAe,EACf,WAAW,EACX,KAAK,EACL,SAAS,EACT,aAAa,EACb,SAAS,EACT,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,EACL,WAAW,EACX,UAAU,EACV,QAAQ,EACR,SAAS,EACT,MAAM,EACN,OAAO,EACP,OAAO,EACP,yBAAyB,EACzB,aAAa,EACb,SAAS,EACT,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,2BAA2B,EAE3B,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,EACjB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,4BAA4B,EAC5B,gCAAgC,EAChC,gCAAgC,EAChC,qCAAqC,EACrC,cAAc,EACd,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iCAAiC,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,MAAM,CAAC;AAE9C,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,wCAAwC,EAAE,MAAM,SAAS,CAAC"}
|