@sentry/cloudflare 9.31.0 → 9.32.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 +0 -2
- package/build/cjs/client.js.map +1 -1
- package/build/cjs/index.js +2 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/pages-plugin.js +3 -1
- package/build/cjs/pages-plugin.js.map +1 -1
- package/build/cjs/sdk.js +3 -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 +0 -2
- package/build/esm/client.js.map +1 -1
- package/build/esm/index.js +1 -0
- package/build/esm/index.js.map +1 -1
- 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/sdk.js +3 -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 +6 -0
- package/build/types/client.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- 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/workflows.d.ts +25 -0
- package/build/types/workflows.d.ts.map +1 -0
- package/build/types-ts3.8/client.d.ts +6 -0
- package/build/types-ts3.8/index.d.ts +1 -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/workflows.d.ts +22 -0
- package/package.json +3 -3
package/build/cjs/client.js
CHANGED
package/build/cjs/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../../src/client.ts"],"sourcesContent":["import type { ClientOptions, Options, ServerRuntimeClientOptions } from '@sentry/core';\nimport { applySdkMetadata, ServerRuntimeClient } from '@sentry/core';\nimport type { CloudflareTransportOptions } from './transport';\n\n/**\n * The Sentry Cloudflare SDK Client.\n *\n * @see CloudflareClientOptions for documentation on configuration options.\n * @see ServerRuntimeClient for usage documentation.\n */\nexport class CloudflareClient extends ServerRuntimeClient<CloudflareClientOptions> {\n /**\n * Creates a new Cloudflare SDK instance.\n * @param options Configuration options for this SDK.\n */\n public constructor(options: CloudflareClientOptions) {\n applySdkMetadata(options, 'cloudflare');\n options._metadata = options._metadata || {};\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'javascript',\n // TODO: Grab version information\n runtime: { name: 'cloudflare' },\n // TODO: Add server name\n };\n\n super(clientOptions);\n }\n}\n\n
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../src/client.ts"],"sourcesContent":["import type { ClientOptions, Options, ServerRuntimeClientOptions } from '@sentry/core';\nimport { applySdkMetadata, ServerRuntimeClient } from '@sentry/core';\nimport type { CloudflareTransportOptions } from './transport';\n\n/**\n * The Sentry Cloudflare SDK Client.\n *\n * @see CloudflareClientOptions for documentation on configuration options.\n * @see ServerRuntimeClient for usage documentation.\n */\nexport class CloudflareClient extends ServerRuntimeClient<CloudflareClientOptions> {\n /**\n * Creates a new Cloudflare SDK instance.\n * @param options Configuration options for this SDK.\n */\n public constructor(options: CloudflareClientOptions) {\n applySdkMetadata(options, 'cloudflare');\n options._metadata = options._metadata || {};\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'javascript',\n // TODO: Grab version information\n runtime: { name: 'cloudflare' },\n // TODO: Add server name\n };\n\n super(clientOptions);\n }\n}\n\ninterface BaseCloudflareOptions {\n /**\n * @ignore Used internally to disable the deDupeIntegration for workflows.\n * @hidden Used internally to disable the deDupeIntegration for workflows.\n * @default true\n */\n enableDedupe?: boolean;\n}\n\n/**\n * Configuration options for the Sentry Cloudflare SDK\n *\n * @see @sentry/core Options for more information.\n */\nexport interface CloudflareOptions extends Options<CloudflareTransportOptions>, BaseCloudflareOptions {}\n\n/**\n * Configuration options for the Sentry Cloudflare SDK Client class\n *\n * @see CloudflareClient for more information.\n */\nexport interface CloudflareClientOptions extends ClientOptions<CloudflareTransportOptions>, BaseCloudflareOptions {}\n"],"names":["ServerRuntimeClient","applySdkMetadata"],"mappings":";;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,gBAAA,SAAyBA,wBAAmB,CAA0B;AACnF;AACA;AACA;AACA;AACA,GAAS,WAAW,CAAC,OAAO,EAA2B;AACvD,IAAIC,qBAAgB,CAAC,OAAO,EAAE,YAAY,CAAC;AAC3C,IAAI,OAAO,CAAC,SAAU,GAAE,OAAO,CAAC,SAAA,IAAa,EAAE;;AAE/C,IAAI,MAAM,aAAa,GAA+B;AACtD,MAAM,GAAG,OAAO;AAChB,MAAM,QAAQ,EAAE,YAAY;AAC5B;AACA,MAAM,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc;AACrC;AACA,KAAK;;AAEL,IAAI,KAAK,CAAC,aAAa,CAAC;AACxB;AACA;;;;"}
|
package/build/cjs/index.js
CHANGED
|
@@ -10,6 +10,7 @@ const client = require('./client.js');
|
|
|
10
10
|
const sdk = require('./sdk.js');
|
|
11
11
|
const fetch = require('./integrations/fetch.js');
|
|
12
12
|
const d1 = require('./d1.js');
|
|
13
|
+
const workflows = require('./workflows.js');
|
|
13
14
|
const async = require('./async.js');
|
|
14
15
|
|
|
15
16
|
|
|
@@ -94,5 +95,6 @@ exports.CloudflareClient = client.CloudflareClient;
|
|
|
94
95
|
exports.getDefaultIntegrations = sdk.getDefaultIntegrations;
|
|
95
96
|
exports.fetchIntegration = fetch.fetchIntegration;
|
|
96
97
|
exports.instrumentD1WithSentry = d1.instrumentD1WithSentry;
|
|
98
|
+
exports.instrumentWorkflowWithSentry = workflows.instrumentWorkflowWithSentry;
|
|
97
99
|
exports.setAsyncLocalStorageAsyncContextStrategy = async.setAsyncLocalStorageAsyncContextStrategy;
|
|
98
100
|
//# sourceMappingURL=index.js.map
|
package/build/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -44,7 +44,9 @@ function sentryPagesPlugin
|
|
|
44
44
|
async.setAsyncLocalStorageAsyncContextStrategy();
|
|
45
45
|
return context => {
|
|
46
46
|
const options = typeof handlerOrOptions === 'function' ? handlerOrOptions(context) : handlerOrOptions;
|
|
47
|
-
return request.wrapRequestHandler({ options, request: context.request, context }, () =>
|
|
47
|
+
return request.wrapRequestHandler({ options, request: context.request, context: { ...context, props: {} } }, () =>
|
|
48
|
+
context.next(),
|
|
49
|
+
);
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -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":["setAsyncLocalStorageAsyncContextStrategy","wrapRequestHandler"],"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,EAAEA,8CAAwC,EAAE;AAC5C,EAAE,OAAO,WAAW;AACpB,IAAI,MAAM,OAAA,GAAU,OAAO,gBAAiB,KAAI,UAAW,GAAE,gBAAgB,CAAC,OAAO,CAAA,GAAI,gBAAgB;AACzG,IAAI,OAAOC,0BAAkB,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/cjs/sdk.js
CHANGED
|
@@ -10,7 +10,9 @@ const stacktrace = require('./vendor/stacktrace.js');
|
|
|
10
10
|
function getDefaultIntegrations(options) {
|
|
11
11
|
const sendDefaultPii = options.sendDefaultPii ?? false;
|
|
12
12
|
return [
|
|
13
|
-
|
|
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 ? [] : [core.dedupeIntegration()]),
|
|
14
16
|
// TODO(v10): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`
|
|
15
17
|
// eslint-disable-next-line deprecation/deprecation
|
|
16
18
|
core.inboundFiltersIntegration(),
|
package/build/cjs/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":["dedupeIntegration","inboundFiltersIntegration","functionToStringIntegration","linkedErrorsIntegration","fetchIntegration","requestDataIntegration","consoleIntegration","stackParserFromStackParserOptions","defaultStackParser","getIntegrationsToSetup","makeCloudflareTransport","initAndBind","CloudflareClient"],"mappings":";;;;;;;;AAkBA;AACO,SAAS,sBAAsB,CAAC,OAAO,EAAoC;AAClF,EAAE,MAAM,cAAe,GAAE,OAAO,CAAC,cAAA,IAAkB,KAAK;AACxD,EAAE,OAAO;AACT,
|
|
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 // 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 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":["dedupeIntegration","inboundFiltersIntegration","functionToStringIntegration","linkedErrorsIntegration","fetchIntegration","requestDataIntegration","consoleIntegration","stackParserFromStackParserOptions","defaultStackParser","getIntegrationsToSetup","makeCloudflareTransport","initAndBind","CloudflareClient"],"mappings":";;;;;;;;AAkBA;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,CAACA,sBAAiB,EAAE,CAAC,CAAC;AACpE;AACA;AACA,IAAIC,8BAAyB,EAAE;AAC/B,IAAIC,gCAA2B,EAAE;AACjC,IAAIC,4BAAuB,EAAE;AAC7B,IAAIC,sBAAgB,EAAE;AACtB;AACA,IAAIC,2BAAsB,CAAC,cAAe,GAAE,YAAY,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,KAAM,EAAA,EAAG,CAAC;AACxF,IAAIC,uBAAkB,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,aAAa,GAA4B;AACjD,IAAI,GAAG,OAAO;AACd,IAAI,WAAW,EAAEC,sCAAiC,CAAC,OAAO,CAAC,WAAA,IAAeC,6BAAkB,CAAC;AAC7F,IAAI,YAAY,EAAEC,2BAAsB,CAAC,OAAO,CAAC;AACjD,IAAI,SAAS,EAAE,OAAO,CAAC,SAAA,IAAaC,iCAAuB;AAC3D,GAAG;;AAEH,EAAE,OAAOC,gBAAW,CAACC,uBAAgB,EAAE,aAAa,CAAE;AACtD;;;;;"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
const async = require('./async.js');
|
|
5
|
+
const scopeUtils = require('./scope-utils.js');
|
|
6
|
+
const sdk = require('./sdk.js');
|
|
7
|
+
|
|
8
|
+
const UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i;
|
|
9
|
+
|
|
10
|
+
function propagationContextFromInstanceId(instanceId) {
|
|
11
|
+
// Validate and normalize traceId - should be a valid UUID with or without hyphens
|
|
12
|
+
if (!UUID_REGEX.test(instanceId)) {
|
|
13
|
+
throw new Error("Invalid 'instanceId' for workflow: Sentry requires random UUIDs for instanceId.");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Remove hyphens to get UUID without hyphens
|
|
17
|
+
const traceId = instanceId.replace(/-/g, '');
|
|
18
|
+
|
|
19
|
+
// Derive sampleRand from last 4 characters of the random UUID
|
|
20
|
+
//
|
|
21
|
+
// We cannot store any state between workflow steps, so we derive the
|
|
22
|
+
// sampleRand from the traceId itself. This ensures that the sampling is
|
|
23
|
+
// consistent across all steps in the same workflow instance.
|
|
24
|
+
const sampleRand = parseInt(traceId.slice(-4), 16) / 0xffff;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
traceId,
|
|
28
|
+
sampleRand,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function workflowStepWithSentry(
|
|
33
|
+
instanceId,
|
|
34
|
+
options,
|
|
35
|
+
callback,
|
|
36
|
+
) {
|
|
37
|
+
async.setAsyncLocalStorageAsyncContextStrategy();
|
|
38
|
+
|
|
39
|
+
return core.withIsolationScope(async isolationScope => {
|
|
40
|
+
const client = sdk.init({ ...options, enableDedupe: false });
|
|
41
|
+
isolationScope.setClient(client);
|
|
42
|
+
|
|
43
|
+
scopeUtils.addCloudResourceContext(isolationScope);
|
|
44
|
+
|
|
45
|
+
return core.withScope(async scope => {
|
|
46
|
+
const propagationContext = propagationContextFromInstanceId(instanceId);
|
|
47
|
+
scope.setPropagationContext(propagationContext);
|
|
48
|
+
|
|
49
|
+
// eslint-disable-next-line no-return-await
|
|
50
|
+
return await callback();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
class WrappedWorkflowStep {
|
|
56
|
+
constructor(
|
|
57
|
+
_instanceId,
|
|
58
|
+
_ctx,
|
|
59
|
+
_options,
|
|
60
|
+
_step,
|
|
61
|
+
) {this._instanceId = _instanceId;this._ctx = _ctx;this._options = _options;this._step = _step;}
|
|
62
|
+
|
|
63
|
+
async do(
|
|
64
|
+
name,
|
|
65
|
+
configOrCallback,
|
|
66
|
+
maybeCallback,
|
|
67
|
+
) {
|
|
68
|
+
const userCallback = (maybeCallback || configOrCallback) ;
|
|
69
|
+
const config = typeof configOrCallback === 'function' ? undefined : configOrCallback;
|
|
70
|
+
|
|
71
|
+
const instrumentedCallback = async () => {
|
|
72
|
+
return workflowStepWithSentry(this._instanceId, this._options, async () => {
|
|
73
|
+
return core.startSpan(
|
|
74
|
+
{
|
|
75
|
+
op: 'function.step.do',
|
|
76
|
+
name,
|
|
77
|
+
attributes: {
|
|
78
|
+
'cloudflare.workflow.timeout': config?.timeout,
|
|
79
|
+
'cloudflare.workflow.retries.backoff': config?.retries?.backoff,
|
|
80
|
+
'cloudflare.workflow.retries.delay': config?.retries?.delay,
|
|
81
|
+
'cloudflare.workflow.retries.limit': config?.retries?.limit,
|
|
82
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',
|
|
83
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
async span => {
|
|
87
|
+
try {
|
|
88
|
+
const result = await userCallback();
|
|
89
|
+
span.setStatus({ code: 1 });
|
|
90
|
+
return result;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
core.captureException(error, { mechanism: { handled: true, type: 'cloudflare' } });
|
|
93
|
+
throw error;
|
|
94
|
+
} finally {
|
|
95
|
+
this._ctx.waitUntil(core.flush(2000));
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
return config ? this._step.do(name, config, instrumentedCallback) : this._step.do(name, instrumentedCallback);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async sleep(name, duration) {
|
|
106
|
+
return this._step.sleep(name, duration);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async sleepUntil(name, timestamp) {
|
|
110
|
+
return this._step.sleepUntil(name, timestamp);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async waitForEvent(
|
|
114
|
+
name,
|
|
115
|
+
options,
|
|
116
|
+
) {
|
|
117
|
+
return this._step.waitForEvent(name, options);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Instruments a Cloudflare Workflow class with Sentry.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const InstrumentedWorkflow = instrumentWorkflowWithSentry(
|
|
127
|
+
* (env) => ({ dsn: env.SENTRY_DSN }),
|
|
128
|
+
* MyWorkflowClass
|
|
129
|
+
* );
|
|
130
|
+
*
|
|
131
|
+
* export default InstrumentedWorkflow;
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @param optionsCallback - Function that returns Sentry options to initialize Sentry
|
|
135
|
+
* @param WorkflowClass - The workflow class to instrument
|
|
136
|
+
* @returns Instrumented workflow class with the same interface
|
|
137
|
+
*/
|
|
138
|
+
function instrumentWorkflowWithSentry
|
|
139
|
+
|
|
140
|
+
(optionsCallback, WorkFlowClass) {
|
|
141
|
+
return new Proxy(WorkFlowClass, {
|
|
142
|
+
construct(target, args, newTarget) {
|
|
143
|
+
const [ctx, env] = args;
|
|
144
|
+
const options = optionsCallback(env);
|
|
145
|
+
const instance = Reflect.construct(target, args, newTarget) ;
|
|
146
|
+
return new Proxy(instance, {
|
|
147
|
+
get(obj, prop, receiver) {
|
|
148
|
+
if (prop === 'run') {
|
|
149
|
+
return async function (event, step) {
|
|
150
|
+
return obj.run.call(obj, event, new WrappedWorkflowStep(event.instanceId, ctx, options, step));
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return Reflect.get(obj, prop, receiver);
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
}) ;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
exports.instrumentWorkflowWithSentry = instrumentWorkflowWithSentry;
|
|
161
|
+
//# 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":["setAsyncLocalStorageAsyncContextStrategy","withIsolationScope","init","addCloudResourceContext","withScope","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","captureException","flush"],"mappings":"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"}
|
package/build/esm/client.js
CHANGED
package/build/esm/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../../src/client.ts"],"sourcesContent":["import type { ClientOptions, Options, ServerRuntimeClientOptions } from '@sentry/core';\nimport { applySdkMetadata, ServerRuntimeClient } from '@sentry/core';\nimport type { CloudflareTransportOptions } from './transport';\n\n/**\n * The Sentry Cloudflare SDK Client.\n *\n * @see CloudflareClientOptions for documentation on configuration options.\n * @see ServerRuntimeClient for usage documentation.\n */\nexport class CloudflareClient extends ServerRuntimeClient<CloudflareClientOptions> {\n /**\n * Creates a new Cloudflare SDK instance.\n * @param options Configuration options for this SDK.\n */\n public constructor(options: CloudflareClientOptions) {\n applySdkMetadata(options, 'cloudflare');\n options._metadata = options._metadata || {};\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'javascript',\n // TODO: Grab version information\n runtime: { name: 'cloudflare' },\n // TODO: Add server name\n };\n\n super(clientOptions);\n }\n}\n\n
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../src/client.ts"],"sourcesContent":["import type { ClientOptions, Options, ServerRuntimeClientOptions } from '@sentry/core';\nimport { applySdkMetadata, ServerRuntimeClient } from '@sentry/core';\nimport type { CloudflareTransportOptions } from './transport';\n\n/**\n * The Sentry Cloudflare SDK Client.\n *\n * @see CloudflareClientOptions for documentation on configuration options.\n * @see ServerRuntimeClient for usage documentation.\n */\nexport class CloudflareClient extends ServerRuntimeClient<CloudflareClientOptions> {\n /**\n * Creates a new Cloudflare SDK instance.\n * @param options Configuration options for this SDK.\n */\n public constructor(options: CloudflareClientOptions) {\n applySdkMetadata(options, 'cloudflare');\n options._metadata = options._metadata || {};\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'javascript',\n // TODO: Grab version information\n runtime: { name: 'cloudflare' },\n // TODO: Add server name\n };\n\n super(clientOptions);\n }\n}\n\ninterface BaseCloudflareOptions {\n /**\n * @ignore Used internally to disable the deDupeIntegration for workflows.\n * @hidden Used internally to disable the deDupeIntegration for workflows.\n * @default true\n */\n enableDedupe?: boolean;\n}\n\n/**\n * Configuration options for the Sentry Cloudflare SDK\n *\n * @see @sentry/core Options for more information.\n */\nexport interface CloudflareOptions extends Options<CloudflareTransportOptions>, BaseCloudflareOptions {}\n\n/**\n * Configuration options for the Sentry Cloudflare SDK Client class\n *\n * @see CloudflareClient for more information.\n */\nexport interface CloudflareClientOptions extends ClientOptions<CloudflareTransportOptions>, BaseCloudflareOptions {}\n"],"names":[],"mappings":";;AAIA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,gBAAA,SAAyB,mBAAmB,CAA0B;AACnF;AACA;AACA;AACA;AACA,GAAS,WAAW,CAAC,OAAO,EAA2B;AACvD,IAAI,gBAAgB,CAAC,OAAO,EAAE,YAAY,CAAC;AAC3C,IAAI,OAAO,CAAC,SAAU,GAAE,OAAO,CAAC,SAAA,IAAa,EAAE;;AAE/C,IAAI,MAAM,aAAa,GAA+B;AACtD,MAAM,GAAG,OAAO;AAChB,MAAM,QAAQ,EAAE,YAAY;AAC5B;AACA,MAAM,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc;AACrC;AACA,KAAK;;AAEL,IAAI,KAAK,CAAC,aAAa,CAAC;AACxB;AACA;;;;"}
|
package/build/esm/index.js
CHANGED
|
@@ -9,5 +9,6 @@ export { CloudflareClient } from './client.js';
|
|
|
9
9
|
export { getDefaultIntegrations } from './sdk.js';
|
|
10
10
|
export { fetchIntegration } from './integrations/fetch.js';
|
|
11
11
|
export { instrumentD1WithSentry } from './d1.js';
|
|
12
|
+
export { instrumentWorkflowWithSentry } from './workflows.js';
|
|
12
13
|
export { setAsyncLocalStorageAsyncContextStrategy } from './async.js';
|
|
13
14
|
//# sourceMappingURL=index.js.map
|
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"9.
|
|
1
|
+
{"type":"module","version":"9.32.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/sdk.js
CHANGED
|
@@ -8,7 +8,9 @@ import { defaultStackParser } from './vendor/stacktrace.js';
|
|
|
8
8
|
function getDefaultIntegrations(options) {
|
|
9
9
|
const sendDefaultPii = options.sendDefaultPii ?? false;
|
|
10
10
|
return [
|
|
11
|
-
|
|
11
|
+
// The Dedupe integration should not be used in workflows because we want to
|
|
12
|
+
// capture all step failures, even if they are the same error.
|
|
13
|
+
...(options.enableDedupe === false ? [] : [dedupeIntegration()]),
|
|
12
14
|
// TODO(v10): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`
|
|
13
15
|
// eslint-disable-next-line deprecation/deprecation
|
|
14
16
|
inboundFiltersIntegration(),
|
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":";;;;;;AAkBA;AACO,SAAS,sBAAsB,CAAC,OAAO,EAAoC;AAClF,EAAE,MAAM,cAAe,GAAE,OAAO,CAAC,cAAA,IAAkB,KAAK;AACxD,EAAE,OAAO;AACT,IAAI,iBAAiB,EAAE;
|
|
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 // 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 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":";;;;;;AAkBA;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,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,GAAG;;AAEH,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
|
@@ -15,6 +15,12 @@ export declare class CloudflareClient extends ServerRuntimeClient<CloudflareClie
|
|
|
15
15
|
constructor(options: CloudflareClientOptions);
|
|
16
16
|
}
|
|
17
17
|
interface BaseCloudflareOptions {
|
|
18
|
+
/**
|
|
19
|
+
* @ignore Used internally to disable the deDupeIntegration for workflows.
|
|
20
|
+
* @hidden Used internally to disable the deDupeIntegration for workflows.
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
enableDedupe?: boolean;
|
|
18
24
|
}
|
|
19
25
|
/**
|
|
20
26
|
* Configuration options for the Sentry Cloudflare SDK
|
|
@@ -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,uBAAuB,CAAC;IAChF;;;OAGG;gBACgB,OAAO,EAAE,uBAAuB;CAcpD;
|
|
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,uBAAuB,CAAC;IAChF;;;OAGG;gBACgB,OAAO,EAAE,uBAAuB;CAcpD;AAED,UAAU,qBAAqB;IAC7B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO,CAAC,0BAA0B,CAAC,EAAE,qBAAqB;CAAG;AAExG;;;;GAIG;AACH,MAAM,WAAW,uBAAwB,SAAQ,aAAa,CAAC,0BAA0B,CAAC,EAAE,qBAAqB;CAAG"}
|
package/build/types/index.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ export { CloudflareClient } from './client';
|
|
|
10
10
|
export { getDefaultIntegrations } from './sdk';
|
|
11
11
|
export { fetchIntegration } from './integrations/fetch';
|
|
12
12
|
export { instrumentD1WithSentry } from './d1';
|
|
13
|
+
export { instrumentWorkflowWithSentry } from './workflows';
|
|
13
14
|
export { setAsyncLocalStorageAsyncContextStrategy } from './async';
|
|
14
15
|
//# 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;AAExD,OAAO,EAAE,sBAAsB,EAAE,MAAM,MAAM,CAAC;AAE9C,OAAO,EAAE,wCAAwC,EAAE,MAAM,SAAS,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;AAExD,OAAO,EAAE,sBAAsB,EAAE,MAAM,MAAM,CAAC;AAE9C,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,wCAAwC,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-plugin.d.ts","sourceRoot":"","sources":["../../src/pages-plugin.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAG,OAAO,EAEb,MAAM,SAAS,MAAM,GAAG,GAAG,EAC3B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG9D,YAAY,GAAG,GAAG,EAElB,gBAAgB,EACZ,iBAAiB,GACjB,CAAC,CAAC,OAAO,EAAE,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,KAAK,iBAAiB,CAAC,GACxF,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"pages-plugin.d.ts","sourceRoot":"","sources":["../../src/pages-plugin.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAG,OAAO,EAEb,MAAM,SAAS,MAAM,GAAG,GAAG,EAC3B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG9D,YAAY,GAAG,GAAG,EAElB,gBAAgB,EACZ,iBAAiB,GACjB,CAAC,CAAC,OAAO,EAAE,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,KAAK,iBAAiB,CAAC,GACxF,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,CAQtD"}
|
package/build/types/request.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAY/F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAIlD,UAAU,4BAA4B;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,cAAc,EAAE,4BAA4B,EAC5C,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAC5D,OAAO,CAAC,QAAQ,CAAC,CAsEnB"}
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/request.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAY/F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAIlD,UAAU,4BAA4B;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,cAAc,EAAE,4BAA4B,EAC5C,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAC5D,OAAO,CAAC,QAAQ,CAAC,CAsEnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-utils.d.ts","sourceRoot":"","sources":["../../src/scope-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAG1C;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAI1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,2BAA2B,GAAG,IAAI,CAIrF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAE/D"}
|
|
1
|
+
{"version":3,"file":"scope-utils.d.ts","sourceRoot":"","sources":["../../src/scope-utils.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAG1C;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAI1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,2BAA2B,GAAG,IAAI,CAIrF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAE/D"}
|
package/build/types/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAYhD,OAAO,KAAK,EAA2B,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAK5C,2DAA2D;AAC3D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAYhD,OAAO,KAAK,EAA2B,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAK5C,2DAA2D;AAC3D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,WAAW,EAAE,CAgBhF;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,GAAG,SAAS,CAa7E"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import type { WorkflowEntrypoint } from 'cloudflare:workers';
|
|
3
|
+
import type { CloudflareOptions } from './client';
|
|
4
|
+
/**
|
|
5
|
+
* Instruments a Cloudflare Workflow class with Sentry.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const InstrumentedWorkflow = instrumentWorkflowWithSentry(
|
|
10
|
+
* (env) => ({ dsn: env.SENTRY_DSN }),
|
|
11
|
+
* MyWorkflowClass
|
|
12
|
+
* );
|
|
13
|
+
*
|
|
14
|
+
* export default InstrumentedWorkflow;
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @param optionsCallback - Function that returns Sentry options to initialize Sentry
|
|
18
|
+
* @param WorkflowClass - The workflow class to instrument
|
|
19
|
+
* @returns Instrumented workflow class with the same interface
|
|
20
|
+
*/
|
|
21
|
+
export declare function instrumentWorkflowWithSentry<E, // Environment type
|
|
22
|
+
P, // Payload type
|
|
23
|
+
T extends WorkflowEntrypoint<E, P>, // WorkflowEntrypoint type
|
|
24
|
+
C extends new (ctx: ExecutionContext, env: E) => T>(optionsCallback: (env: E) => CloudflareOptions, WorkFlowClass: C): C;
|
|
25
|
+
//# sourceMappingURL=workflows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/workflows.ts"],"names":[],"mappings":";AAUA,OAAO,KAAK,EACV,kBAAkB,EAOnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AA2HlD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAC1C,CAAC,EAAE,mBAAmB;AACtB,CAAC,EAAE,eAAe;AAClB,CAAC,SAAS,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,0BAA0B;AAC9D,CAAC,SAAS,KAAK,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EAClD,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,iBAAiB,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,CAkBrE"}
|
|
@@ -15,6 +15,12 @@ export declare class CloudflareClient extends ServerRuntimeClient<CloudflareClie
|
|
|
15
15
|
constructor(options: CloudflareClientOptions);
|
|
16
16
|
}
|
|
17
17
|
interface BaseCloudflareOptions {
|
|
18
|
+
/**
|
|
19
|
+
* @ignore Used internally to disable the deDupeIntegration for workflows.
|
|
20
|
+
* @hidden Used internally to disable the deDupeIntegration for workflows.
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
enableDedupe?: boolean;
|
|
18
24
|
}
|
|
19
25
|
/**
|
|
20
26
|
* Configuration options for the Sentry Cloudflare SDK
|
|
@@ -11,5 +11,6 @@ export { CloudflareClient } from './client';
|
|
|
11
11
|
export { getDefaultIntegrations } from './sdk';
|
|
12
12
|
export { fetchIntegration } from './integrations/fetch';
|
|
13
13
|
export { instrumentD1WithSentry } from './d1';
|
|
14
|
+
export { instrumentWorkflowWithSentry } from './workflows';
|
|
14
15
|
export { setAsyncLocalStorageAsyncContextStrategy } from './async';
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import { WorkflowEntrypoint } from 'cloudflare:workers';
|
|
3
|
+
import { CloudflareOptions } from './client';
|
|
4
|
+
/**
|
|
5
|
+
* Instruments a Cloudflare Workflow class with Sentry.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const InstrumentedWorkflow = instrumentWorkflowWithSentry(
|
|
10
|
+
* (env) => ({ dsn: env.SENTRY_DSN }),
|
|
11
|
+
* MyWorkflowClass
|
|
12
|
+
* );
|
|
13
|
+
*
|
|
14
|
+
* export default InstrumentedWorkflow;
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @param optionsCallback - Function that returns Sentry options to initialize Sentry
|
|
18
|
+
* @param WorkflowClass - The workflow class to instrument
|
|
19
|
+
* @returns Instrumented workflow class with the same interface
|
|
20
|
+
*/
|
|
21
|
+
export declare function instrumentWorkflowWithSentry<E, P, T extends WorkflowEntrypoint<E, P>, C extends new (ctx: ExecutionContext, env: E) => T>(optionsCallback: (env: E) => CloudflareOptions, WorkFlowClass: C): C;
|
|
22
|
+
//# sourceMappingURL=workflows.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/cloudflare",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.32.0",
|
|
4
4
|
"description": "Official Sentry SDK for Cloudflare Workers and Pages",
|
|
5
5
|
"repository": "git://github.com/getsentry/sentry-javascript.git",
|
|
6
6
|
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/cloudflare",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"access": "public"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@sentry/core": "9.
|
|
52
|
+
"@sentry/core": "9.32.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@cloudflare/workers-types": "^4.x"
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@cloudflare/workers-types": "4.
|
|
63
|
+
"@cloudflare/workers-types": "4.20250620.0",
|
|
64
64
|
"@types/node": "^18.19.1",
|
|
65
65
|
"wrangler": "^3.67.1"
|
|
66
66
|
},
|