@sentry/cloudflare 11.0.0-rc.1 → 11.1.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/README.md +8 -200
- package/build/cjs/dev/client.js +11 -4
- package/build/cjs/dev/client.js.map +1 -1
- package/build/cjs/dev/index.js +1 -0
- package/build/cjs/dev/index.js.map +1 -1
- package/build/cjs/dev/instrumentations/instrumentDurableObjectNamespace.js +3 -0
- package/build/cjs/dev/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/cjs/dev/instrumentations/worker/instrumentEnv.js +3 -0
- package/build/cjs/dev/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/cjs/dev/instrumentations/worker/instrumentQueueProducer.js +2 -1
- package/build/cjs/dev/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
- package/build/cjs/dev/request.js +2 -0
- package/build/cjs/dev/request.js.map +1 -1
- package/build/cjs/dev/transport.js +18 -4
- package/build/cjs/dev/transport.js.map +1 -1
- package/build/cjs/dev/vite/flueRuntime.js +6 -35
- package/build/cjs/dev/vite/flueRuntime.js.map +1 -1
- package/build/cjs/dev/vite/mastraObservability.js +6 -30
- package/build/cjs/dev/vite/mastraObservability.js.map +1 -1
- package/build/cjs/dev/vite/providedModulePlugin.js +53 -0
- package/build/cjs/dev/vite/providedModulePlugin.js.map +1 -0
- package/build/cjs/dev/vite/transform.js +26 -29
- package/build/cjs/dev/vite/transform.js.map +1 -1
- package/build/cjs/dev/workflows.js +7 -2
- package/build/cjs/dev/workflows.js.map +1 -1
- package/build/cjs/prod/client.js +11 -4
- package/build/cjs/prod/client.js.map +1 -1
- package/build/cjs/prod/index.js +1 -0
- package/build/cjs/prod/index.js.map +1 -1
- package/build/cjs/prod/instrumentations/instrumentDurableObjectNamespace.js +3 -0
- package/build/cjs/prod/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/cjs/prod/instrumentations/worker/instrumentEnv.js +3 -0
- package/build/cjs/prod/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/cjs/prod/instrumentations/worker/instrumentQueueProducer.js +2 -1
- package/build/cjs/prod/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
- package/build/cjs/prod/request.js +2 -0
- package/build/cjs/prod/request.js.map +1 -1
- package/build/cjs/prod/transport.js +18 -4
- package/build/cjs/prod/transport.js.map +1 -1
- package/build/cjs/prod/vite/flueRuntime.js +6 -35
- package/build/cjs/prod/vite/flueRuntime.js.map +1 -1
- package/build/cjs/prod/vite/mastraObservability.js +6 -30
- package/build/cjs/prod/vite/mastraObservability.js.map +1 -1
- package/build/cjs/prod/vite/providedModulePlugin.js +53 -0
- package/build/cjs/prod/vite/providedModulePlugin.js.map +1 -0
- package/build/cjs/prod/vite/transform.js +26 -29
- package/build/cjs/prod/vite/transform.js.map +1 -1
- package/build/cjs/prod/workflows.js +7 -2
- package/build/cjs/prod/workflows.js.map +1 -1
- package/build/esm/dev/client.js +11 -4
- package/build/esm/dev/client.js.map +1 -1
- package/build/esm/dev/index.js +1 -1
- package/build/esm/dev/instrumentations/instrumentDurableObjectNamespace.js +3 -0
- package/build/esm/dev/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/esm/dev/instrumentations/worker/instrumentEnv.js +3 -0
- package/build/esm/dev/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/esm/dev/instrumentations/worker/instrumentQueueProducer.js +2 -1
- package/build/esm/dev/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
- package/build/esm/dev/package.json +1 -1
- package/build/esm/dev/request.js +1 -0
- package/build/esm/dev/request.js.map +1 -1
- package/build/esm/dev/transport.js +19 -5
- package/build/esm/dev/transport.js.map +1 -1
- package/build/esm/dev/vite/flueRuntime.js +7 -35
- package/build/esm/dev/vite/flueRuntime.js.map +1 -1
- package/build/esm/dev/vite/mastraObservability.js +7 -30
- package/build/esm/dev/vite/mastraObservability.js.map +1 -1
- package/build/esm/dev/vite/providedModulePlugin.js +50 -0
- package/build/esm/dev/vite/providedModulePlugin.js.map +1 -0
- package/build/esm/dev/vite/transform.js +26 -29
- package/build/esm/dev/vite/transform.js.map +1 -1
- package/build/esm/dev/workflows.js +7 -2
- package/build/esm/dev/workflows.js.map +1 -1
- package/build/esm/prod/client.js +11 -4
- package/build/esm/prod/client.js.map +1 -1
- package/build/esm/prod/index.js +1 -1
- package/build/esm/prod/instrumentations/instrumentDurableObjectNamespace.js +3 -0
- package/build/esm/prod/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/esm/prod/instrumentations/worker/instrumentEnv.js +3 -0
- package/build/esm/prod/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/esm/prod/instrumentations/worker/instrumentQueueProducer.js +2 -1
- package/build/esm/prod/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
- package/build/esm/prod/package.json +1 -1
- package/build/esm/prod/request.js +1 -0
- package/build/esm/prod/request.js.map +1 -1
- package/build/esm/prod/transport.js +19 -5
- package/build/esm/prod/transport.js.map +1 -1
- package/build/esm/prod/vite/flueRuntime.js +7 -35
- package/build/esm/prod/vite/flueRuntime.js.map +1 -1
- package/build/esm/prod/vite/mastraObservability.js +7 -30
- package/build/esm/prod/vite/mastraObservability.js.map +1 -1
- package/build/esm/prod/vite/providedModulePlugin.js +50 -0
- package/build/esm/prod/vite/providedModulePlugin.js.map +1 -0
- package/build/esm/prod/vite/transform.js +26 -29
- package/build/esm/prod/vite/transform.js.map +1 -1
- package/build/esm/prod/workflows.js +7 -2
- package/build/esm/prod/workflows.js.map +1 -1
- package/build/types/client.d.ts +5 -3
- package/build/types/client.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentQueueProducer.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/transport.d.ts +5 -0
- package/build/types/transport.d.ts.map +1 -1
- package/build/types/vite/flueRuntime.d.ts +2 -13
- package/build/types/vite/flueRuntime.d.ts.map +1 -1
- package/build/types/vite/mastraObservability.d.ts +8 -23
- package/build/types/vite/mastraObservability.d.ts.map +1 -1
- package/build/types/vite/providedModulePlugin.d.ts +62 -0
- package/build/types/vite/providedModulePlugin.d.ts.map +1 -0
- package/build/types/workflows.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -1,39 +1,15 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const node_path = require('node:path');
|
|
5
|
-
const MagicString = require('magic-string');
|
|
3
|
+
const providedModulePlugin = require('./providedModulePlugin.js');
|
|
6
4
|
|
|
7
|
-
const PROVIDER_IDENTIFIER = "__SENTRY_MASTRA_OBSERVABILITY__";
|
|
8
|
-
const MASTRA_INTEGRATION_ID = /@sentry\/server-utils\/build\/esm\/integrations\/mastra\.js$/;
|
|
9
|
-
function isMastraIntegrationModuleId(id) {
|
|
10
|
-
const normalizedId = id.replace(/\\/g, "/").replace(/[?#].*$/, "");
|
|
11
|
-
return MASTRA_INTEGRATION_ID.test(normalizedId);
|
|
12
|
-
}
|
|
13
5
|
function sentryMastraObservabilityProviderPlugin() {
|
|
14
|
-
|
|
15
|
-
return {
|
|
6
|
+
return providedModulePlugin.createProvidedModulePlugin({
|
|
16
7
|
name: "sentry-cloudflare-mastra-observability-provider",
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
providerSnippet = `import * as ${PROVIDER_IDENTIFIER} from '@mastra/observability';
|
|
24
|
-
(globalThis.__SENTRY_ORCHESTRION__ = globalThis.__SENTRY_ORCHESTRION__ || {});
|
|
25
|
-
(globalThis.__SENTRY_ORCHESTRION__.providedModules = globalThis.__SENTRY_ORCHESTRION__.providedModules || {})['@mastra/observability'] = ${PROVIDER_IDENTIFIER};
|
|
26
|
-
`;
|
|
27
|
-
},
|
|
28
|
-
transform(code, id) {
|
|
29
|
-
if (!providerSnippet || !isMastraIntegrationModuleId(id)) return void 0;
|
|
30
|
-
const ms = new MagicString.default(code);
|
|
31
|
-
ms.prepend(providerSnippet);
|
|
32
|
-
return { code: ms.toString(), map: ms.generateMap({ hires: true }) };
|
|
33
|
-
}
|
|
34
|
-
};
|
|
8
|
+
moduleName: "@mastra/observability",
|
|
9
|
+
identifier: "__SENTRY_MASTRA_OBSERVABILITY__",
|
|
10
|
+
integrationModule: "mastra"
|
|
11
|
+
});
|
|
35
12
|
}
|
|
36
13
|
|
|
37
|
-
exports.isMastraIntegrationModuleId = isMastraIntegrationModuleId;
|
|
38
14
|
exports.sentryMastraObservabilityProviderPlugin = sentryMastraObservabilityProviderPlugin;
|
|
39
15
|
//# sourceMappingURL=mastraObservability.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mastraObservability.js","sources":["../../../../src/vite/mastraObservability.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"mastraObservability.js","sources":["../../../../src/vite/mastraObservability.ts"],"sourcesContent":["import type { ProvidedModulePlugin } from './providedModulePlugin';\nimport { createProvidedModulePlugin } from './providedModulePlugin';\n\n/**\n * Splices a static `import * as … from '@mastra/observability'` into Sentry's own Mastra\n * integration module and stashes the namespace on the global orchestrion marker.\n *\n * On Cloudflare the integration cannot `createRequire('@mastra/observability')` to bootstrap\n * Mastra's observability pipeline — there is no on-disk `node_modules` in workerd — so without\n * this the user has to construct and wire up an `Observability` themselves. If the package is\n * absent, the integration keeps its Node `createRequire` fallback and the marker stays empty.\n */\nexport function sentryMastraObservabilityProviderPlugin(): ProvidedModulePlugin {\n return createProvidedModulePlugin({\n name: 'sentry-cloudflare-mastra-observability-provider',\n moduleName: '@mastra/observability',\n identifier: '__SENTRY_MASTRA_OBSERVABILITY__',\n integrationModule: 'mastra',\n });\n}\n"],"names":["createProvidedModulePlugin"],"mappings":";;;;AAYO,SAAS,uCAAA,GAAgE;AAC9E,EAAA,OAAOA,+CAAA,CAA2B;AAAA,IAChC,IAAA,EAAM,iDAAA;AAAA,IACN,UAAA,EAAY,uBAAA;AAAA,IACZ,UAAA,EAAY,iCAAA;AAAA,IACZ,iBAAA,EAAmB;AAAA,GACpB,CAAA;AACH;;;;"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const node_path = require('node:path');
|
|
4
|
+
const MagicString = require('magic-string');
|
|
5
|
+
|
|
6
|
+
function createIntegrationModuleMatcher(integrationModule) {
|
|
7
|
+
const suffix = `@sentry/server-utils/build/esm/integrations/${integrationModule}.js`;
|
|
8
|
+
return (id) => id.replace(/\\/g, "/").replace(/[?#].*$/, "").endsWith(suffix);
|
|
9
|
+
}
|
|
10
|
+
function buildProviderSnippet({ moduleName, identifier }) {
|
|
11
|
+
const marker = "globalThis.__SENTRY_ORCHESTRION__";
|
|
12
|
+
return `import * as ${identifier} from '${moduleName}';
|
|
13
|
+
(${marker} = ${marker} || {});
|
|
14
|
+
(${marker}.providedModules = ${marker}.providedModules || {});
|
|
15
|
+
Object.defineProperty(${marker}.providedModules, '${moduleName}', { configurable: true, enumerable: true, get() { return ${identifier}; } });
|
|
16
|
+
`;
|
|
17
|
+
}
|
|
18
|
+
function createProvidedModulePlugin(options) {
|
|
19
|
+
const isIntegrationModuleId = createIntegrationModuleMatcher(options.integrationModule);
|
|
20
|
+
let root = process.cwd();
|
|
21
|
+
let providerSnippet;
|
|
22
|
+
return {
|
|
23
|
+
name: options.name,
|
|
24
|
+
applyToEnvironment(environment) {
|
|
25
|
+
return environment.config.consumer === "server";
|
|
26
|
+
},
|
|
27
|
+
configResolved(config) {
|
|
28
|
+
root = config.root;
|
|
29
|
+
},
|
|
30
|
+
async buildStart() {
|
|
31
|
+
if (providerSnippet) return;
|
|
32
|
+
try {
|
|
33
|
+
const resolved = await this.resolve(options.moduleName, node_path.resolve(root, "noop.js"));
|
|
34
|
+
if (!resolved) return;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
this.warn(
|
|
37
|
+
`[Sentry] could not resolve ${options.moduleName} while probing for it; injecting the provider anyway. ${error?.message ?? error}`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
providerSnippet = buildProviderSnippet(options);
|
|
41
|
+
},
|
|
42
|
+
transform(code, id) {
|
|
43
|
+
if (!providerSnippet || !isIntegrationModuleId(id) || code.includes(options.identifier)) return void 0;
|
|
44
|
+
const ms = new MagicString.default(code);
|
|
45
|
+
ms.prepend(providerSnippet);
|
|
46
|
+
return { code: ms.toString(), map: ms.generateMap({ hires: true }) };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
exports.createIntegrationModuleMatcher = createIntegrationModuleMatcher;
|
|
52
|
+
exports.createProvidedModulePlugin = createProvidedModulePlugin;
|
|
53
|
+
//# sourceMappingURL=providedModulePlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providedModulePlugin.js","sources":["../../../../src/vite/providedModulePlugin.ts"],"sourcesContent":["import { resolve } from 'node:path';\nimport MagicString from 'magic-string';\n\n/**\n * The slice of the Rollup plugin context the probe needs. Declared here rather than imported so\n * this file carries no Rollup or Vite type dependency.\n */\ninterface ResolveContext {\n resolve(\n source: string,\n importer?: string,\n options?: { skipSelf?: boolean },\n ): Promise<{ id: string; external?: boolean | string } | null>;\n warn(message: string): void;\n}\n\n/** The plugin shape `sentryCloudflareVitePlugin` composes. */\nexport interface ProvidedModulePlugin {\n name: string;\n applyToEnvironment(environment: { config: { consumer: string } }): boolean;\n configResolved(config: { root: string }): void;\n buildStart(this: ResolveContext): Promise<void>;\n transform(code: string, id: string): { code: string; map: ReturnType<MagicString['generateMap']> } | undefined;\n}\n\nexport interface ProvidedModulePluginOptions {\n /** Vite plugin name, e.g. `sentry-cloudflare-flue-runtime-provider`. */\n name: string;\n /** Bare specifier of the package to provide, e.g. `@flue/runtime`. */\n moduleName: string;\n /** Namespace binding the injected import uses, e.g. `__SENTRY_FLUE_RUNTIME__`. */\n identifier: string;\n /** Basename of the `@sentry/server-utils` integration module to inject into, e.g. `flue`. */\n integrationModule: string;\n}\n\n/**\n * Build the matcher for one `@sentry/server-utils` integration module.\n *\n * Plain `endsWith`, not a `RegExp`: nothing here needs pattern matching, and building one from\n * a caller-supplied string would need escaping, which is the only reason this file would have to\n * import from `@sentry/core`. A build-time plugin should not drag the SDK into the build.\n */\nexport function createIntegrationModuleMatcher(integrationModule: string): (id: string) => boolean {\n // The ESM build only: a worker never loads the CJS one.\n const suffix = `@sentry/server-utils/build/esm/integrations/${integrationModule}.js`;\n\n return (id: string): boolean =>\n id\n .replace(/\\\\/g, '/')\n .replace(/[?#].*$/, '')\n .endsWith(suffix);\n}\n\nfunction buildProviderSnippet({ moduleName, identifier }: ProvidedModulePluginOptions): string {\n const marker = 'globalThis.__SENTRY_ORCHESTRION__';\n\n // A getter, not an assignment: assigning reads the binding at injection time, so it stores\n // `undefined` whenever the bundler evaluates Sentry's module before the provided package\n // finished initializing. Enumerable so the entry shows up in `Object.keys` and a spread.\n return (\n `import * as ${identifier} from '${moduleName}';\\n` +\n `(${marker} = ${marker} || {});\\n` +\n `(${marker}.providedModules = ${marker}.providedModules || {});\\n` +\n `Object.defineProperty(${marker}.providedModules, '${moduleName}', ` +\n `{ configurable: true, enumerable: true, get() { return ${identifier}; } });\\n`\n );\n}\n\n/**\n * Build a Vite plugin that splices a static `import * as … from '<moduleName>'` into one of\n * Sentry's own integration modules and exposes the namespace on the global orchestrion marker.\n *\n * Some packages are instrumented by registration rather than by patching, so instrumenting them\n * needs a reference to that module's own binding and no channel payload carries one. On Node the\n * integration resolves it itself; a bundled worker has no `node_modules` to resolve from, so the\n * binding is supplied at build time instead. The import is static, lands in Sentry's module rather\n * than the user's code, and is only emitted when the package actually resolves.\n */\nexport function createProvidedModulePlugin(options: ProvidedModulePluginOptions): ProvidedModulePlugin {\n const isIntegrationModuleId = createIntegrationModuleMatcher(options.integrationModule);\n\n let root = process.cwd();\n let providerSnippet: string | undefined;\n\n return {\n name: options.name,\n\n applyToEnvironment(environment: { config: { consumer: string } }): boolean {\n // Server environments only. `buildStart` runs per environment against one shared plugin\n // instance, so without this a `client` build resolves first, under browser conditions, and\n // answers on the worker's behalf. That defeats the point of probing with `this.resolve`.\n // Same gate the orchestrion plugin uses.\n return environment.config.consumer === 'server';\n },\n\n configResolved(config: { root: string }): void {\n root = config.root;\n },\n\n async buildStart(this: ResolveContext): Promise<void> {\n // Already answered by an earlier server environment. A build with several worker\n // environments shares the answer: they resolve under the same conditions.\n if (providerSnippet) return;\n\n try {\n // The environment's own resolver, so the probe uses the conditions the injected import\n // will. That is what a `require.resolve` probe cannot do: an ESM-only package has no\n // `require` condition and reads as missing. Resolved from the app root, not from Sentry's\n // own install.\n const resolved = await this.resolve(options.moduleName, resolve(root, 'noop.js'));\n if (!resolved) return;\n } catch (error) {\n // Present but unresolvable for some other reason. Inject anyway so the build fails loudly\n // rather than silently shipping a worker with no instrumentation, and surface the original\n // cause: the import error Vite raises next says nothing about why resolution broke.\n this.warn(\n `[Sentry] could not resolve ${options.moduleName} while probing for it; injecting the provider anyway. ${\n (error as Error | undefined)?.message ?? error\n }`,\n );\n }\n\n providerSnippet = buildProviderSnippet(options);\n },\n\n transform(code: string, id: string): { code: string; map: ReturnType<MagicString['generateMap']> } | undefined {\n // `code.includes` keeps this idempotent: a second pass over already-injected output would\n // otherwise emit a duplicate `import * as` binding, which is a syntax error.\n if (!providerSnippet || !isIntegrationModuleId(id) || code.includes(options.identifier)) return undefined;\n\n const ms = new MagicString(code);\n ms.prepend(providerSnippet);\n return { code: ms.toString(), map: ms.generateMap({ hires: true }) };\n },\n };\n}\n"],"names":["resolve","MagicString"],"mappings":";;;;;AA2CO,SAAS,+BAA+B,iBAAA,EAAoD;AAEjG,EAAA,MAAM,MAAA,GAAS,+CAA+C,iBAAiB,CAAA,GAAA,CAAA;AAE/E,EAAA,OAAO,CAAC,EAAA,KACN,EAAA,CACG,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAClB,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA,CACrB,QAAA,CAAS,MAAM,CAAA;AACtB;AAEA,SAAS,oBAAA,CAAqB,EAAE,UAAA,EAAY,UAAA,EAAW,EAAwC;AAC7F,EAAA,MAAM,MAAA,GAAS,mCAAA;AAKf,EAAA,OACE,CAAA,YAAA,EAAe,UAAU,CAAA,OAAA,EAAU,UAAU,CAAA;AAAA,CAAA,EACzC,MAAM,MAAM,MAAM,CAAA;AAAA,CAAA,EAClB,MAAM,sBAAsB,MAAM,CAAA;AAAA,sBAAA,EACb,MAAM,CAAA,mBAAA,EAAsB,UAAU,CAAA,0DAAA,EACL,UAAU,CAAA;AAAA,CAAA;AAExE;AAYO,SAAS,2BAA2B,OAAA,EAA4D;AACrG,EAAA,MAAM,qBAAA,GAAwB,8BAAA,CAA+B,OAAA,CAAQ,iBAAiB,CAAA;AAEtF,EAAA,IAAI,IAAA,GAAO,QAAQ,GAAA,EAAI;AACvB,EAAA,IAAI,eAAA;AAEJ,EAAA,OAAO;AAAA,IACL,MAAM,OAAA,CAAQ,IAAA;AAAA,IAEd,mBAAmB,WAAA,EAAwD;AAKzE,MAAA,OAAO,WAAA,CAAY,OAAO,QAAA,KAAa,QAAA;AAAA,IACzC,CAAA;AAAA,IAEA,eAAe,MAAA,EAAgC;AAC7C,MAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,IAChB,CAAA;AAAA,IAEA,MAAM,UAAA,GAAgD;AAGpD,MAAA,IAAI,eAAA,EAAiB;AAErB,MAAA,IAAI;AAKF,QAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAQ,UAAA,EAAYA,iBAAA,CAAQ,IAAA,EAAM,SAAS,CAAC,CAAA;AAChF,QAAA,IAAI,CAAC,QAAA,EAAU;AAAA,MACjB,SAAS,KAAA,EAAO;AAId,QAAA,IAAA,CAAK,IAAA;AAAA,UACH,8BAA8B,OAAA,CAAQ,UAAU,CAAA,sDAAA,EAC7C,KAAA,EAA6B,WAAW,KAC3C,CAAA;AAAA,SACF;AAAA,MACF;AAEA,MAAA,eAAA,GAAkB,qBAAqB,OAAO,CAAA;AAAA,IAChD,CAAA;AAAA,IAEA,SAAA,CAAU,MAAc,EAAA,EAAuF;AAG7G,MAAA,IAAI,CAAC,eAAA,IAAmB,CAAC,qBAAA,CAAsB,EAAE,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA,EAAG,OAAO,MAAA;AAEhG,MAAA,MAAM,EAAA,GAAK,IAAIC,mBAAA,CAAY,IAAI,CAAA;AAC/B,MAAA,EAAA,CAAG,QAAQ,eAAe,CAAA;AAC1B,MAAA,OAAO,EAAE,IAAA,EAAM,EAAA,CAAG,QAAA,EAAS,EAAG,GAAA,EAAK,EAAA,CAAG,WAAA,CAAY,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA,EAAE;AAAA,IACrE;AAAA,GACF;AACF;;;;;"}
|
|
@@ -28,7 +28,7 @@ function applyAutoInstrumentTransforms(code, ast, ctx) {
|
|
|
28
28
|
needsImport: false,
|
|
29
29
|
wrappedClasses: /* @__PURE__ */ new Set(),
|
|
30
30
|
topLevelClasses,
|
|
31
|
-
|
|
31
|
+
wrappedLocals: /* @__PURE__ */ new Map(),
|
|
32
32
|
classWrappers: ctx.classWrappers,
|
|
33
33
|
agentClasses: ctx.agentClasses ?? /* @__PURE__ */ new Set(),
|
|
34
34
|
workerEntrypointClasses: workerEntrypoint.detectWorkerEntrypointClasses(ast),
|
|
@@ -109,9 +109,13 @@ function collectTopLevelClasses(ast) {
|
|
|
109
109
|
function wrapDefaultExport(node, ctx, state) {
|
|
110
110
|
const decl = node.declaration;
|
|
111
111
|
if (isCallToMethod(decl, "withSentry")) return;
|
|
112
|
-
if (decl.type === "Identifier"
|
|
113
|
-
state.
|
|
114
|
-
|
|
112
|
+
if (decl.type === "Identifier") {
|
|
113
|
+
const wrappedName = state.wrappedLocals.get(decl.name);
|
|
114
|
+
if (wrappedName) {
|
|
115
|
+
state.ms.overwrite(decl.start, decl.end, wrappedName);
|
|
116
|
+
state.autoWrapped.add(wranglerConfig.DEFAULT_EXPORT);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
115
119
|
}
|
|
116
120
|
state.ms.overwrite(node.start, decl.start, "const __SENTRY_DEFAULT_EXPORT__ = ");
|
|
117
121
|
state.ms.append(`
|
|
@@ -148,19 +152,26 @@ function wrapInlineClassExport(exportNode, classDecl, ctx, state) {
|
|
|
148
152
|
const kind = classId ? resolveWrapperKind(classId.name, classId.name, state) : void 0;
|
|
149
153
|
if (!classId || !kind) return;
|
|
150
154
|
const className = classId.name;
|
|
151
|
-
const renamedClass = `__SENTRY_ORIGINAL_${className}__`;
|
|
152
155
|
state.ms.overwrite(exportNode.start, classDecl.start, "");
|
|
153
|
-
|
|
156
|
+
const wrappedName = wrapLocalClass(className, classDecl, kind, state);
|
|
157
|
+
state.ms.appendLeft(exportNode.end, `export { ${wrappedName} as ${className} };
|
|
158
|
+
`);
|
|
159
|
+
state.wrappedClasses.add(className);
|
|
160
|
+
state.autoWrapped.add(className);
|
|
161
|
+
}
|
|
162
|
+
function wrapLocalClass(localName, localClass, kind, state) {
|
|
163
|
+
const existing = state.wrappedLocals.get(localName);
|
|
164
|
+
if (existing) return existing;
|
|
165
|
+
const wrappedName = `__SENTRY_WRAPPED_${localName}__`;
|
|
166
|
+
state.wrappedLocals.set(localName, wrappedName);
|
|
154
167
|
state.ms.appendLeft(
|
|
155
|
-
|
|
168
|
+
localClass.end,
|
|
156
169
|
`
|
|
157
|
-
|
|
170
|
+
const ${wrappedName} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${localName});
|
|
158
171
|
`
|
|
159
172
|
);
|
|
160
|
-
state.wrappedClasses.add(className);
|
|
161
|
-
state.autoWrapped.add(className);
|
|
162
|
-
state.renamedLocals.add(className);
|
|
163
173
|
state.needsImport = true;
|
|
174
|
+
return wrappedName;
|
|
164
175
|
}
|
|
165
176
|
function wrapSpecifierExports(node, ctx, state) {
|
|
166
177
|
const specifiers = node.specifiers ?? [];
|
|
@@ -170,7 +181,7 @@ function wrapSpecifierExports(node, ctx, state) {
|
|
|
170
181
|
const wrappedPairs = [];
|
|
171
182
|
const kept = [];
|
|
172
183
|
for (const specifier of specifiers) {
|
|
173
|
-
const pair =
|
|
184
|
+
const pair = wrapSpecifier(specifier, sourceLiteral, ctx, state, prelude);
|
|
174
185
|
if (pair) {
|
|
175
186
|
wrappedPairs.push(pair);
|
|
176
187
|
} else {
|
|
@@ -185,7 +196,7 @@ function wrapSpecifierExports(node, ctx, state) {
|
|
|
185
196
|
}
|
|
186
197
|
state.ms.overwrite(node.start, node.end, statements.join("\n"));
|
|
187
198
|
}
|
|
188
|
-
function
|
|
199
|
+
function wrapSpecifier(specifier, sourceLiteral, ctx, state, prelude) {
|
|
189
200
|
const exportedName = specifier.type === "ExportSpecifier" && specifier.exported?.type === "Identifier" ? specifier.exported.name : void 0;
|
|
190
201
|
const localName = specifier.local?.type === "Identifier" ? specifier.local.name : void 0;
|
|
191
202
|
const kind = exportedName ? resolveWrapperKind(exportedName, sourceLiteral ? void 0 : localName, state) : void 0;
|
|
@@ -193,10 +204,9 @@ function wrapCrossModuleSpecifier(specifier, sourceLiteral, ctx, state, prelude)
|
|
|
193
204
|
if (!sourceLiteral) {
|
|
194
205
|
const localClass = state.topLevelClasses.get(localName);
|
|
195
206
|
if (localClass?.id) {
|
|
196
|
-
|
|
207
|
+
const wrappedName2 = wrapLocalClass(localName, localClass, kind, state);
|
|
197
208
|
state.wrappedClasses.add(exportedName);
|
|
198
|
-
|
|
199
|
-
return void 0;
|
|
209
|
+
return `${wrappedName2} as ${exportedName}`;
|
|
200
210
|
}
|
|
201
211
|
if (state.manuallyWrappedLocals.has(localName)) {
|
|
202
212
|
state.wrappedClasses.add(exportedName);
|
|
@@ -219,19 +229,6 @@ function wrapCrossModuleSpecifier(specifier, sourceLiteral, ctx, state, prelude)
|
|
|
219
229
|
state.needsImport = true;
|
|
220
230
|
return `${wrappedName} as ${exportedName}`;
|
|
221
231
|
}
|
|
222
|
-
function wrapLocalClassExport(localName, localClass, kind, ctx, state) {
|
|
223
|
-
const classId = localClass.id;
|
|
224
|
-
if (!classId || state.renamedLocals.has(localName)) return;
|
|
225
|
-
state.renamedLocals.add(localName);
|
|
226
|
-
const renamedClass = `__SENTRY_ORIGINAL_${localName}__`;
|
|
227
|
-
state.ms.overwrite(classId.start, classId.end, renamedClass);
|
|
228
|
-
state.ms.appendLeft(
|
|
229
|
-
localClass.end,
|
|
230
|
-
`
|
|
231
|
-
const ${localName} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass});
|
|
232
|
-
`
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
232
|
|
|
236
233
|
exports.applyAutoInstrumentTransforms = applyAutoInstrumentTransforms;
|
|
237
234
|
//# sourceMappingURL=transform.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.js","sources":["../../../../src/vite/transform.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport MagicString from 'magic-string';\nimport { DEFAULT_EXPORT, type ExportName, type SameWorkerBinding } from './wranglerConfig';\nimport { detectWorkerEntrypointClasses } from './workerEntrypoint';\n\nconst MERGED_OPTIONS_IDENTIFIER = '__SENTRY_OPTIONS__';\n\n// ---------------------------------------------------------------------------\n// Minimal ESTree node types for the AST nodes we inspect.\n// ---------------------------------------------------------------------------\n\nexport interface BaseNode {\n type: string;\n start: number;\n end: number;\n}\n\nexport interface ProgramBody {\n body: BaseNode[];\n}\n\ninterface IdentifierNode extends BaseNode {\n name: string;\n}\n\ninterface CalleeNode {\n type: string;\n name?: string;\n property?: { type: string; name?: string };\n}\n\ninterface CallExpressionNode extends BaseNode {\n callee?: CalleeNode;\n}\n\ninterface ClassDeclarationNode extends BaseNode {\n id?: IdentifierNode | null;\n}\n\ninterface ExportDefaultNode extends BaseNode {\n declaration: BaseNode;\n}\n\ninterface ExportSpecifierNode extends BaseNode {\n local?: { type: string; name?: string };\n exported?: { type: string; name?: string };\n}\n\ninterface ExportNamedNode extends BaseNode {\n declaration?: BaseNode | null;\n source?: BaseNode | null;\n specifiers?: ExportSpecifierNode[];\n}\n\ninterface VariableDeclaratorNode {\n id?: { type: string; name?: string };\n init?: BaseNode | null;\n}\n\ninterface VariableDeclarationNode extends BaseNode {\n declarations?: VariableDeclaratorNode[];\n}\n\nfunction isCallToMethod(node: BaseNode, methodName: string): boolean {\n if (node.type !== 'CallExpression') return false;\n const callee = (node as CallExpressionNode).callee;\n if (!callee) return false;\n if (callee.type === 'Identifier' && callee.name === methodName) return true;\n return (\n callee.type === 'MemberExpression' && callee.property?.type === 'Identifier' && callee.property.name === methodName\n );\n}\n\n/**\n * The kind of Sentry wrapper to apply to an exported class.\n *\n * `durableObject` and `workflow` are keyed by name from the wrangler config\n * (`durable_objects.bindings`, `workflows`), since those class names are\n * authoritative there. `workerEntrypoint` is different: a worker's own\n * entrypoints aren't enumerated in its config, so they're detected structurally\n * (a class extending `WorkerEntrypoint` from `cloudflare:workers`), with the\n * config providing only a fallback for self-bound entrypoints whose base class\n * lives in another module.\n */\nexport type ClassWrapperKind = 'durableObject' | 'agent' | 'workflow' | 'workerEntrypoint';\n\n/** Specifier name a `export { default as X } from '...'` re-export uses for the source's default. */\nconst DEFAULT_IMPORT = 'default';\n\n/**\n * The `@sentry/cloudflare` helper each wrapper kind emits. All share the same\n * `(optionsCallback, Class)` signature. `WorkerEntrypoint` classes use\n * `withSentry`, which runtime-detects the class type and routes accordingly.\n */\nconst WRAPPER_METHODS: Record<ClassWrapperKind, string> = {\n durableObject: 'instrumentDurableObjectWithSentry',\n agent: 'instrumentAgentWithSentry',\n workflow: 'instrumentWorkflowWithSentry',\n workerEntrypoint: 'withSentry',\n};\n\nexport interface TransformContext {\n /**\n * Exported class name → the kind of Sentry wrapper to apply. Populated from\n * the wrangler config, so the transform can wrap by name without resolving\n * each class's base type.\n */\n classWrappers: Map<string, ClassWrapperKind>;\n /**\n * Local class names detected as `agents` Agents. An Agent is configured as a Durable Object in\n * wrangler, so this upgrades those entries from `durableObject` to `agent`.\n */\n agentClasses?: ReadonlySet<string>;\n optionsFn: string;\n /** Import statement prepended when `optionsFn` references a separate module. */\n optionsImport?: string;\n /** @see {@link import('./wranglerConfig').WranglerConfig.sameWorkerBindings} */\n sameWorkerBindings?: readonly SameWorkerBinding[];\n}\n\nexport interface TransformResult {\n code: string;\n map: ReturnType<MagicString['generateMap']>;\n /**\n * The configured class names that were actually wrapped. Lets the plugin warn\n * about configured classes it could not find, instead of silently leaving\n * them uninstrumented.\n */\n wrappedClasses: Set<string>;\n}\n\n/**\n * Rewrite the worker entry source to wrap its default export with `withSentry`\n * and any configured class export with its matching Sentry wrapper (see\n * {@link TransformContext.classWrappers}, e.g. Durable Object classes with\n * `instrumentDurableObjectWithSentry`).\n *\n * Handles `export class MyDO {}`, the specifier form (`class MyDO {}` …\n * `export { MyDO }` / `export { Foo as MyDO }`), and classes that live in\n * another module (`import { MyDO } from './do'; export { MyDO }` or\n * `export { MyDO } from './do'`). Only star re-exports (`export * from './do'`)\n * are left alone — the plugin warns about those via\n * {@link TransformResult.wrappedClasses}.\n *\n * Exported (rather than inlined into the plugin) so it can be unit-tested with a\n * plain AST and no Vite context. Returns `undefined` when nothing was wrapped and\n * there are no already-manually-wrapped classes to report.\n */\nexport function applyAutoInstrumentTransforms(\n code: string,\n ast: ProgramBody,\n ctx: TransformContext,\n): TransformResult | undefined {\n const ms = new MagicString(code);\n const topLevelClasses = collectTopLevelClasses(ast);\n const sameWorkerBindings = ctx.sameWorkerBindings ?? [];\n const state: TransformState = {\n ms,\n needsImport: false,\n wrappedClasses: new Set<string>(),\n topLevelClasses,\n renamedLocals: new Set<string>(),\n classWrappers: ctx.classWrappers,\n agentClasses: ctx.agentClasses ?? new Set<string>(),\n workerEntrypointClasses: detectWorkerEntrypointClasses(ast),\n // The identifier must be chosen before wrapping, which bindings survive is only known after.\n optionsFn: sameWorkerBindings.length > 0 ? MERGED_OPTIONS_IDENTIFIER : ctx.optionsFn,\n autoWrapped: new Set<ExportName>(),\n manuallyWrappedLocals: collectManuallyWrappedLocals(ast),\n };\n const { wrappedClasses } = state;\n\n // Named exports first, regardless of source order: the default-export handler\n // needs to know which local bindings a named export already wrapped, so it can\n // skip a class that is both exported by name and re-exported as default (which\n // would otherwise wrap it twice).\n for (const node of ast.body) {\n if (node.type === 'ExportNamedDeclaration') {\n handleNamedExport(node, ctx, state);\n }\n }\n for (const node of ast.body) {\n if (node.type === 'ExportDefaultDeclaration') {\n wrapDefaultExport(node as ExportDefaultNode, ctx, state);\n }\n }\n\n if (!state.needsImport) {\n // Nothing was rewritten. Still surface any classes found already wrapped\n // manually (via `wrappedClasses`) so the caller doesn't warn about them;\n // return undefined only when there was nothing to report either.\n if (wrappedClasses.size === 0) return undefined;\n return { code, map: ms.generateMap({ hires: true }), wrappedClasses };\n }\n\n // `prepend` inserts before earlier prepends, yielding: Sentry import, options import, declaration.\n if (sameWorkerBindings.length > 0) {\n ms.prepend(buildMergedOptionsDeclaration(sameWorkerBindings, ctx.optionsFn, state));\n }\n if (ctx.optionsImport) ms.prepend(ctx.optionsImport);\n ms.prepend(\"import * as __SENTRY__ from '@sentry/cloudflare';\\n\");\n\n return {\n code: ms.toString(),\n map: ms.generateMap({ hires: true }),\n wrappedClasses,\n };\n}\n\ninterface TransformState {\n ms: MagicString;\n needsImport: boolean;\n wrappedClasses: Set<string>;\n /**\n * Top-level (non-exported) class declarations, so specifier exports like\n * `export { MyDO }` can locate the class they refer to.\n */\n topLevelClasses: Map<string, ClassDeclarationNode>;\n /**\n * Local class names already renamed + wrapped, so two specifiers pointing at\n * the same class don't produce duplicate bindings.\n */\n renamedLocals: Set<string>;\n /** Class name → wrapper kind, keyed by the *exported* name (from config). */\n classWrappers: Map<string, ClassWrapperKind>;\n /** Local class names detected as `agents` Agents (see {@link TransformContext.agentClasses}). */\n agentClasses: ReadonlySet<string>;\n /**\n * Local class names detected as `WorkerEntrypoint` subclasses in this module,\n * so they can be wrapped without a config entry.\n */\n workerEntrypointClasses: Set<string>;\n optionsFn: string;\n /**\n * Export names wrapped by this transform, so their options can be extended with\n * `rpcTracePropagationBindings`. Hand-wrapped exports stay out, they keep the options they were\n * wrapped with. `wrappedClasses` counts both.\n */\n autoWrapped: Set<ExportName>;\n /**\n * Top-level bindings already assigned an `instrument*WithSentry(...)` result\n * (`const MyDO = instrumentDurableObjectWithSentry(...)`). Exporting one by\n * specifier must report it as wrapped rather than wrap it a second time.\n */\n manuallyWrappedLocals: Set<string>;\n}\n\n/**\n * Builds the callback that merges same-worker binding names into `rpcTracePropagationBindings` at\n * runtime, the options object only exists once the callback runs with `env`. Only bindings whose\n * class this transform wrapped survive, a hand-wrapped class runs on its own options.\n */\nfunction buildMergedOptionsDeclaration(\n sameWorkerBindings: readonly SameWorkerBinding[],\n optionsFn: string,\n state: TransformState,\n): string {\n const bindingNames = sameWorkerBindings\n .filter(({ className }) => state.autoWrapped.has(className))\n .map(({ bindingName }) => bindingName);\n\n if (!bindingNames.length) {\n return `const ${MERGED_OPTIONS_IDENTIFIER} = ${optionsFn};\\n`;\n }\n\n const names = bindingNames.map(name => JSON.stringify(name)).join(', ');\n return (\n `const ${MERGED_OPTIONS_IDENTIFIER} = (env) => { ` +\n `const opts = (${optionsFn})(env); ` +\n `return { ...opts, rpcTracePropagationBindings: [${names}, ...(opts?.rpcTracePropagationBindings ?? [])] }; };\\n`\n );\n}\n\n/**\n * Resolve the wrapper kind for a class export.\n *\n * Config (`classWrappers`) wins — it's authoritative for Durable Objects and\n * Workflows, and provides the self-binding fallback for WorkerEntrypoints whose\n * base class this module can't see. Otherwise a structurally-detected\n * `WorkerEntrypoint` subclass (matched by its *local* name) gets wrapped with\n * `withSentry`.\n *\n * `localName` is the binding **in this module** the export refers to, and must be\n * left undefined for `export { X } from '...'`: there the specifier's name belongs\n * to the source module, so matching it against anything detected here would wrap a\n * class that merely shares a name.\n *\n * The one case where config is refined rather than obeyed is an `agents` Agent:\n * it *is* a Durable Object, so wrangler can only ever describe it as one, and\n * only the detected base chain distinguishes the two.\n */\nfunction resolveWrapperKind(\n exportedName: string,\n localName: string | undefined,\n state: TransformState,\n): ClassWrapperKind | undefined {\n const configured = state.classWrappers.get(exportedName);\n\n if (\n configured === 'durableObject' &&\n ((localName && state.agentClasses.has(localName)) || state.agentClasses.has(exportedName))\n ) {\n return 'agent';\n }\n\n if (configured) return configured;\n if (localName && state.workerEntrypointClasses.has(localName)) return 'workerEntrypoint';\n return undefined;\n}\n\n/**\n * Top-level `const X = instrument*WithSentry(...)` bindings — a hand-wrapped class that is exported\n * separately (`export { X }`) rather than inline.\n */\nfunction collectManuallyWrappedLocals(ast: ProgramBody): Set<string> {\n const wrapperMethods = Object.values(WRAPPER_METHODS);\n const locals = new Set<string>();\n\n for (const node of ast.body) {\n if (node.type !== 'VariableDeclaration') continue;\n for (const declarator of (node as VariableDeclarationNode).declarations ?? []) {\n const name = declarator.id?.type === 'Identifier' ? declarator.id.name : undefined;\n const init = declarator.init;\n if (name && init && wrapperMethods.some(method => isCallToMethod(init, method))) {\n locals.add(name);\n }\n }\n }\n\n return locals;\n}\n\nfunction collectTopLevelClasses(ast: ProgramBody): Map<string, ClassDeclarationNode> {\n const classes = new Map<string, ClassDeclarationNode>();\n for (const node of ast.body) {\n if (node.type !== 'ClassDeclaration') continue;\n const classNode = node as ClassDeclarationNode;\n if (classNode.id?.name) classes.set(classNode.id.name, classNode);\n }\n return classes;\n}\n\nfunction wrapDefaultExport(node: ExportDefaultNode, ctx: TransformContext, state: TransformState): void {\n const decl = node.declaration;\n\n // Already wrapped — leave it alone\n if (isCallToMethod(decl, 'withSentry')) return;\n\n // `export default Foo` where `Foo` is a local class already wrapped by a named\n // export (e.g. a self-bound WorkerEntrypoint also used as the default handler).\n // Wrapping again would produce `withSentry(withSentry(...))`. The binding still\n // points at the wrapped class, so the default export counts as auto-wrapped.\n if (decl.type === 'Identifier' && state.renamedLocals.has((decl as IdentifierNode).name)) {\n state.autoWrapped.add(DEFAULT_EXPORT);\n return;\n }\n\n // `export default <expr>` → `const __SENTRY_DEFAULT_EXPORT__ = <expr>`\n // MagicString positions are always relative to the original source.\n state.ms.overwrite(node.start, decl.start, 'const __SENTRY_DEFAULT_EXPORT__ = ');\n state.ms.append(`\\nexport default __SENTRY__.withSentry(${state.optionsFn}, __SENTRY_DEFAULT_EXPORT__);\\n`);\n state.needsImport = true;\n state.autoWrapped.add(DEFAULT_EXPORT);\n}\n\nfunction handleNamedExport(node: ExportNamedNode, ctx: TransformContext, state: TransformState): void {\n const decl = node.declaration;\n\n // ---- Manually wrapped class export ----\n // `export const MyDO = instrumentDurableObjectWithSentry(...)` — count it\n // as wrapped so the plugin doesn't warn about it, but leave it alone.\n if (decl?.type === 'VariableDeclaration') {\n collectManuallyWrappedClassExports(decl, ctx, state);\n return;\n }\n\n // ---- Named class export matching a configured binding ----\n if (decl?.type === 'ClassDeclaration') {\n wrapInlineClassExport(node, decl, ctx, state);\n return;\n }\n\n // ---- Specifier export (`export { Foo as MyDO }`, `export { MyDO } from './do'`) ----\n wrapSpecifierExports(node, ctx, state);\n}\n\nfunction collectManuallyWrappedClassExports(\n varDecl: VariableDeclarationNode,\n ctx: TransformContext,\n state: TransformState,\n): void {\n for (const declarator of varDecl.declarations ?? []) {\n const name = declarator.id?.type === 'Identifier' ? declarator.id.name : undefined;\n const kind = name ? ctx.classWrappers.get(name) : undefined;\n if (!name || !kind || !declarator.init) continue;\n\n // A hand-wrapped Agent is configured as a Durable Object, so accept either helper there —\n // otherwise an already-instrumented Agent would be reported as unwrapped.\n const accepted =\n kind === 'durableObject' ? [WRAPPER_METHODS.durableObject, WRAPPER_METHODS.agent] : [WRAPPER_METHODS[kind]];\n\n if (accepted.some(method => isCallToMethod(declarator.init as BaseNode, method))) {\n state.wrappedClasses.add(name);\n }\n }\n}\n\nfunction wrapInlineClassExport(\n exportNode: ExportNamedNode,\n classDecl: ClassDeclarationNode,\n ctx: TransformContext,\n state: TransformState,\n): void {\n const classId = classDecl.id;\n // Inline export: the exported name and the local class name are the same.\n const kind = classId ? resolveWrapperKind(classId.name, classId.name, state) : undefined;\n if (!classId || !kind) return;\n\n const className = classId.name;\n const renamedClass = `__SENTRY_ORIGINAL_${className}__`;\n\n // Strip the `export ` keyword\n state.ms.overwrite(exportNode.start, classDecl.start, '');\n\n // Rename the class to avoid a duplicate binding\n state.ms.overwrite(classId.start, classId.end, renamedClass);\n\n // Insert the wrapped re-export after the class body\n state.ms.appendLeft(\n exportNode.end,\n `\\nexport const ${className} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass});\\n`,\n );\n\n state.wrappedClasses.add(className);\n state.autoWrapped.add(className);\n state.renamedLocals.add(className);\n state.needsImport = true;\n}\n\n/**\n * Wrap the configured classes an `export { ... }` statement names.\n *\n * A class *declared* in this module keeps the statement intact: the declaration is renamed and the\n * wrapper takes over its binding, so the untouched specifier now exports the wrapped class.\n *\n * A class that lives in **another** module — imported and re-exported, or re-exported directly — has\n * no local binding to overwrite (import bindings are immutable). Those specifiers are re-pointed at\n * a fresh wrapper binding instead, which means rebuilding the statement; specifiers this plugin has\n * no business touching are carried over verbatim.\n */\nfunction wrapSpecifierExports(node: ExportNamedNode, ctx: TransformContext, state: TransformState): void {\n const specifiers = node.specifiers ?? [];\n if (specifiers.length === 0) return;\n\n const sourceLiteral = node.source ? state.ms.original.slice(node.source.start, node.source.end) : undefined;\n\n const prelude: string[] = [];\n const wrappedPairs: string[] = [];\n const kept: string[] = [];\n\n for (const specifier of specifiers) {\n const pair = wrapCrossModuleSpecifier(specifier, sourceLiteral, ctx, state, prelude);\n if (pair) {\n wrappedPairs.push(pair);\n } else {\n kept.push(state.ms.original.slice(specifier.start, specifier.end));\n }\n }\n\n if (wrappedPairs.length === 0) return;\n\n const statements = [...prelude, `export { ${wrappedPairs.join(', ')} };`];\n if (kept.length > 0) {\n const clause = `export { ${kept.join(', ')} }`;\n statements.push(sourceLiteral ? `${clause} from ${sourceLiteral};` : `${clause};`);\n }\n state.ms.overwrite(node.start, node.end, statements.join('\\n'));\n}\n\n/**\n * Handle one export specifier, returning the `Wrapped as Exported` pair to emit when its class has\n * to be wrapped through a fresh binding — the cross-module case. The import/wrapper statements that\n * pair depends on are pushed onto `prelude`.\n *\n * Returns `undefined` when the specifier can stay exactly as written: it doesn't name a configured\n * class, its class is declared locally (wrapped in place via {@link wrapLocalClassExport}, which\n * takes over the binding the specifier already exports), or the binding is already hand-wrapped.\n */\nfunction wrapCrossModuleSpecifier(\n specifier: ExportSpecifierNode,\n sourceLiteral: string | undefined,\n ctx: TransformContext,\n state: TransformState,\n prelude: string[],\n): string | undefined {\n const exportedName =\n specifier.type === 'ExportSpecifier' && specifier.exported?.type === 'Identifier'\n ? specifier.exported.name\n : undefined;\n const localName = specifier.local?.type === 'Identifier' ? specifier.local.name : undefined;\n // With a `from` clause the specifier names an export of the *source* module, not a binding here.\n const kind = exportedName\n ? resolveWrapperKind(exportedName, sourceLiteral ? undefined : localName, state)\n : undefined;\n\n if (!exportedName || !localName || !kind) return undefined;\n\n // Without a `from` clause the specifier points at a module-local binding, which may already be\n // (or become) the wrapped class without touching the export statement itself.\n if (!sourceLiteral) {\n const localClass = state.topLevelClasses.get(localName);\n\n if (localClass?.id) {\n wrapLocalClassExport(localName, localClass, kind, ctx, state);\n state.wrappedClasses.add(exportedName);\n state.needsImport = true;\n return undefined;\n }\n\n if (state.manuallyWrappedLocals.has(localName)) {\n state.wrappedClasses.add(exportedName);\n return undefined;\n }\n }\n\n // The class comes from another module: bind it under a private name (for the `from` form, which\n // has no local binding at all), wrap that, and export the wrapper under the configured name.\n let target = localName;\n\n if (sourceLiteral) {\n target = `__SENTRY_REEXPORT_${exportedName}__`;\n prelude.push(\n localName === DEFAULT_IMPORT\n ? `import ${target} from ${sourceLiteral};`\n : `import { ${localName} as ${target} } from ${sourceLiteral};`,\n );\n }\n\n const wrappedName = `__SENTRY_WRAPPED_${exportedName}__`;\n\n // The class may already be hand-wrapped in its own module, which this transform cannot see. The\n // emitted guard returns such a class as-is instead of nesting a second wrapper around it.\n prelude.push(\n `const ${wrappedName} = __SENTRY__._INTERNAL_wrapUnlessInstrumented(__SENTRY__.${WRAPPER_METHODS[kind]}, ${state.optionsFn}, ${target});`,\n );\n state.wrappedClasses.add(exportedName);\n state.autoWrapped.add(exportedName);\n state.needsImport = true;\n\n return `${wrappedName} as ${exportedName}`;\n}\n\n/** Rename a locally declared class and rebind its original name to the wrapper. */\nfunction wrapLocalClassExport(\n localName: string,\n localClass: ClassDeclarationNode,\n kind: ClassWrapperKind,\n ctx: TransformContext,\n state: TransformState,\n): void {\n const classId = localClass.id;\n if (!classId || state.renamedLocals.has(localName)) return;\n state.renamedLocals.add(localName);\n\n const renamedClass = `__SENTRY_ORIGINAL_${localName}__`;\n state.ms.overwrite(classId.start, classId.end, renamedClass);\n state.ms.appendLeft(\n localClass.end,\n `\\nconst ${localName} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass});\\n`,\n );\n}\n"],"names":["MagicString","detectWorkerEntrypointClasses","DEFAULT_EXPORT"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transform.js","sources":["../../../../src/vite/transform.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport MagicString from 'magic-string';\nimport { DEFAULT_EXPORT, type ExportName, type SameWorkerBinding } from './wranglerConfig';\nimport { detectWorkerEntrypointClasses } from './workerEntrypoint';\n\nconst MERGED_OPTIONS_IDENTIFIER = '__SENTRY_OPTIONS__';\n\n// ---------------------------------------------------------------------------\n// Minimal ESTree node types for the AST nodes we inspect.\n// ---------------------------------------------------------------------------\n\nexport interface BaseNode {\n type: string;\n start: number;\n end: number;\n}\n\nexport interface ProgramBody {\n body: BaseNode[];\n}\n\ninterface IdentifierNode extends BaseNode {\n name: string;\n}\n\ninterface CalleeNode {\n type: string;\n name?: string;\n property?: { type: string; name?: string };\n}\n\ninterface CallExpressionNode extends BaseNode {\n callee?: CalleeNode;\n}\n\ninterface ClassDeclarationNode extends BaseNode {\n id?: IdentifierNode | null;\n}\n\ninterface ExportDefaultNode extends BaseNode {\n declaration: BaseNode;\n}\n\ninterface ExportSpecifierNode extends BaseNode {\n local?: { type: string; name?: string };\n exported?: { type: string; name?: string };\n}\n\ninterface ExportNamedNode extends BaseNode {\n declaration?: BaseNode | null;\n source?: BaseNode | null;\n specifiers?: ExportSpecifierNode[];\n}\n\ninterface VariableDeclaratorNode {\n id?: { type: string; name?: string };\n init?: BaseNode | null;\n}\n\ninterface VariableDeclarationNode extends BaseNode {\n declarations?: VariableDeclaratorNode[];\n}\n\nfunction isCallToMethod(node: BaseNode, methodName: string): boolean {\n if (node.type !== 'CallExpression') return false;\n const callee = (node as CallExpressionNode).callee;\n if (!callee) return false;\n if (callee.type === 'Identifier' && callee.name === methodName) return true;\n return (\n callee.type === 'MemberExpression' && callee.property?.type === 'Identifier' && callee.property.name === methodName\n );\n}\n\n/**\n * The kind of Sentry wrapper to apply to an exported class.\n *\n * `durableObject` and `workflow` are keyed by name from the wrangler config\n * (`durable_objects.bindings`, `workflows`), since those class names are\n * authoritative there. `workerEntrypoint` is different: a worker's own\n * entrypoints aren't enumerated in its config, so they're detected structurally\n * (a class extending `WorkerEntrypoint` from `cloudflare:workers`), with the\n * config providing only a fallback for self-bound entrypoints whose base class\n * lives in another module.\n */\nexport type ClassWrapperKind = 'durableObject' | 'agent' | 'workflow' | 'workerEntrypoint';\n\n/** Specifier name a `export { default as X } from '...'` re-export uses for the source's default. */\nconst DEFAULT_IMPORT = 'default';\n\n/**\n * The `@sentry/cloudflare` helper each wrapper kind emits. All share the same\n * `(optionsCallback, Class)` signature. `WorkerEntrypoint` classes use\n * `withSentry`, which runtime-detects the class type and routes accordingly.\n */\nconst WRAPPER_METHODS: Record<ClassWrapperKind, string> = {\n durableObject: 'instrumentDurableObjectWithSentry',\n agent: 'instrumentAgentWithSentry',\n workflow: 'instrumentWorkflowWithSentry',\n workerEntrypoint: 'withSentry',\n};\n\nexport interface TransformContext {\n /**\n * Exported class name → the kind of Sentry wrapper to apply. Populated from\n * the wrangler config, so the transform can wrap by name without resolving\n * each class's base type.\n */\n classWrappers: Map<string, ClassWrapperKind>;\n /**\n * Local class names detected as `agents` Agents. An Agent is configured as a Durable Object in\n * wrangler, so this upgrades those entries from `durableObject` to `agent`.\n */\n agentClasses?: ReadonlySet<string>;\n optionsFn: string;\n /** Import statement prepended when `optionsFn` references a separate module. */\n optionsImport?: string;\n /** @see {@link import('./wranglerConfig').WranglerConfig.sameWorkerBindings} */\n sameWorkerBindings?: readonly SameWorkerBinding[];\n}\n\nexport interface TransformResult {\n code: string;\n map: ReturnType<MagicString['generateMap']>;\n /**\n * The configured class names that were actually wrapped. Lets the plugin warn\n * about configured classes it could not find, instead of silently leaving\n * them uninstrumented.\n */\n wrappedClasses: Set<string>;\n}\n\n/**\n * Rewrite the worker entry source to wrap its default export with `withSentry`\n * and any configured class export with its matching Sentry wrapper (see\n * {@link TransformContext.classWrappers}, e.g. Durable Object classes with\n * `instrumentDurableObjectWithSentry`).\n *\n * Handles `export class MyDO {}`, the specifier form (`class MyDO {}` …\n * `export { MyDO }` / `export { Foo as MyDO }`), and classes that live in\n * another module (`import { MyDO } from './do'; export { MyDO }` or\n * `export { MyDO } from './do'`). Only star re-exports (`export * from './do'`)\n * are left alone — the plugin warns about those via\n * {@link TransformResult.wrappedClasses}.\n *\n * Exported (rather than inlined into the plugin) so it can be unit-tested with a\n * plain AST and no Vite context. Returns `undefined` when nothing was wrapped and\n * there are no already-manually-wrapped classes to report.\n */\nexport function applyAutoInstrumentTransforms(\n code: string,\n ast: ProgramBody,\n ctx: TransformContext,\n): TransformResult | undefined {\n const ms = new MagicString(code);\n const topLevelClasses = collectTopLevelClasses(ast);\n const sameWorkerBindings = ctx.sameWorkerBindings ?? [];\n const state: TransformState = {\n ms,\n needsImport: false,\n wrappedClasses: new Set<string>(),\n topLevelClasses,\n wrappedLocals: new Map<string, string>(),\n classWrappers: ctx.classWrappers,\n agentClasses: ctx.agentClasses ?? new Set<string>(),\n workerEntrypointClasses: detectWorkerEntrypointClasses(ast),\n // The identifier must be chosen before wrapping, which bindings survive is only known after.\n optionsFn: sameWorkerBindings.length > 0 ? MERGED_OPTIONS_IDENTIFIER : ctx.optionsFn,\n autoWrapped: new Set<ExportName>(),\n manuallyWrappedLocals: collectManuallyWrappedLocals(ast),\n };\n const { wrappedClasses } = state;\n\n // Named exports first, regardless of source order: the default-export handler\n // needs to know which local bindings a named export already wrapped, so it can\n // skip a class that is both exported by name and re-exported as default (which\n // would otherwise wrap it twice).\n for (const node of ast.body) {\n if (node.type === 'ExportNamedDeclaration') {\n handleNamedExport(node, ctx, state);\n }\n }\n for (const node of ast.body) {\n if (node.type === 'ExportDefaultDeclaration') {\n wrapDefaultExport(node as ExportDefaultNode, ctx, state);\n }\n }\n\n if (!state.needsImport) {\n // Nothing was rewritten. Still surface any classes found already wrapped\n // manually (via `wrappedClasses`) so the caller doesn't warn about them;\n // return undefined only when there was nothing to report either.\n if (wrappedClasses.size === 0) return undefined;\n return { code, map: ms.generateMap({ hires: true }), wrappedClasses };\n }\n\n // `prepend` inserts before earlier prepends, yielding: Sentry import, options import, declaration.\n if (sameWorkerBindings.length > 0) {\n ms.prepend(buildMergedOptionsDeclaration(sameWorkerBindings, ctx.optionsFn, state));\n }\n if (ctx.optionsImport) ms.prepend(ctx.optionsImport);\n ms.prepend(\"import * as __SENTRY__ from '@sentry/cloudflare';\\n\");\n\n return {\n code: ms.toString(),\n map: ms.generateMap({ hires: true }),\n wrappedClasses,\n };\n}\n\ninterface TransformState {\n ms: MagicString;\n needsImport: boolean;\n wrappedClasses: Set<string>;\n /**\n * Top-level (non-exported) class declarations, so specifier exports like\n * `export { MyDO }` can locate the class they refer to.\n */\n topLevelClasses: Map<string, ClassDeclarationNode>;\n /**\n * Local class name → the binding holding its wrapper, so two exports of the same class share one\n * wrapper and a default export of it can be re-pointed.\n */\n wrappedLocals: Map<string, string>;\n /** Class name → wrapper kind, keyed by the *exported* name (from config). */\n classWrappers: Map<string, ClassWrapperKind>;\n /** Local class names detected as `agents` Agents (see {@link TransformContext.agentClasses}). */\n agentClasses: ReadonlySet<string>;\n /**\n * Local class names detected as `WorkerEntrypoint` subclasses in this module,\n * so they can be wrapped without a config entry.\n */\n workerEntrypointClasses: Set<string>;\n optionsFn: string;\n /**\n * Export names wrapped by this transform, so their options can be extended with\n * `rpcTracePropagationBindings`. Hand-wrapped exports stay out, they keep the options they were\n * wrapped with. `wrappedClasses` counts both.\n */\n autoWrapped: Set<ExportName>;\n /**\n * Top-level bindings already assigned an `instrument*WithSentry(...)` result\n * (`const MyDO = instrumentDurableObjectWithSentry(...)`). Exporting one by\n * specifier must report it as wrapped rather than wrap it a second time.\n */\n manuallyWrappedLocals: Set<string>;\n}\n\n/**\n * Builds the callback that merges same-worker binding names into `rpcTracePropagationBindings` at\n * runtime, the options object only exists once the callback runs with `env`. Only bindings whose\n * class this transform wrapped survive, a hand-wrapped class runs on its own options.\n */\nfunction buildMergedOptionsDeclaration(\n sameWorkerBindings: readonly SameWorkerBinding[],\n optionsFn: string,\n state: TransformState,\n): string {\n const bindingNames = sameWorkerBindings\n .filter(({ className }) => state.autoWrapped.has(className))\n .map(({ bindingName }) => bindingName);\n\n if (!bindingNames.length) {\n return `const ${MERGED_OPTIONS_IDENTIFIER} = ${optionsFn};\\n`;\n }\n\n const names = bindingNames.map(name => JSON.stringify(name)).join(', ');\n return (\n `const ${MERGED_OPTIONS_IDENTIFIER} = (env) => { ` +\n `const opts = (${optionsFn})(env); ` +\n `return { ...opts, rpcTracePropagationBindings: [${names}, ...(opts?.rpcTracePropagationBindings ?? [])] }; };\\n`\n );\n}\n\n/**\n * Resolve the wrapper kind for a class export.\n *\n * Config (`classWrappers`) wins — it's authoritative for Durable Objects and\n * Workflows, and provides the self-binding fallback for WorkerEntrypoints whose\n * base class this module can't see. Otherwise a structurally-detected\n * `WorkerEntrypoint` subclass (matched by its *local* name) gets wrapped with\n * `withSentry`.\n *\n * `localName` is the binding **in this module** the export refers to, and must be\n * left undefined for `export { X } from '...'`: there the specifier's name belongs\n * to the source module, so matching it against anything detected here would wrap a\n * class that merely shares a name.\n *\n * The one case where config is refined rather than obeyed is an `agents` Agent:\n * it *is* a Durable Object, so wrangler can only ever describe it as one, and\n * only the detected base chain distinguishes the two.\n */\nfunction resolveWrapperKind(\n exportedName: string,\n localName: string | undefined,\n state: TransformState,\n): ClassWrapperKind | undefined {\n const configured = state.classWrappers.get(exportedName);\n\n if (\n configured === 'durableObject' &&\n ((localName && state.agentClasses.has(localName)) || state.agentClasses.has(exportedName))\n ) {\n return 'agent';\n }\n\n if (configured) return configured;\n if (localName && state.workerEntrypointClasses.has(localName)) return 'workerEntrypoint';\n return undefined;\n}\n\n/**\n * Top-level `const X = instrument*WithSentry(...)` bindings — a hand-wrapped class that is exported\n * separately (`export { X }`) rather than inline.\n */\nfunction collectManuallyWrappedLocals(ast: ProgramBody): Set<string> {\n const wrapperMethods = Object.values(WRAPPER_METHODS);\n const locals = new Set<string>();\n\n for (const node of ast.body) {\n if (node.type !== 'VariableDeclaration') continue;\n for (const declarator of (node as VariableDeclarationNode).declarations ?? []) {\n const name = declarator.id?.type === 'Identifier' ? declarator.id.name : undefined;\n const init = declarator.init;\n if (name && init && wrapperMethods.some(method => isCallToMethod(init, method))) {\n locals.add(name);\n }\n }\n }\n\n return locals;\n}\n\nfunction collectTopLevelClasses(ast: ProgramBody): Map<string, ClassDeclarationNode> {\n const classes = new Map<string, ClassDeclarationNode>();\n for (const node of ast.body) {\n if (node.type !== 'ClassDeclaration') continue;\n const classNode = node as ClassDeclarationNode;\n if (classNode.id?.name) classes.set(classNode.id.name, classNode);\n }\n return classes;\n}\n\nfunction wrapDefaultExport(node: ExportDefaultNode, ctx: TransformContext, state: TransformState): void {\n const decl = node.declaration;\n\n // Already wrapped — leave it alone\n if (isCallToMethod(decl, 'withSentry')) return;\n\n // `export default Foo` where `Foo` is a local class already wrapped by a named\n // export (e.g. a self-bound WorkerEntrypoint also used as the default handler).\n // Wrapping again would produce `withSentry(withSentry(...))`, so the default\n // export is re-pointed at the wrapper binding the named export created.\n if (decl.type === 'Identifier') {\n const wrappedName = state.wrappedLocals.get((decl as IdentifierNode).name);\n if (wrappedName) {\n state.ms.overwrite(decl.start, decl.end, wrappedName);\n state.autoWrapped.add(DEFAULT_EXPORT);\n return;\n }\n }\n\n // `export default <expr>` → `const __SENTRY_DEFAULT_EXPORT__ = <expr>`\n // MagicString positions are always relative to the original source.\n state.ms.overwrite(node.start, decl.start, 'const __SENTRY_DEFAULT_EXPORT__ = ');\n state.ms.append(`\\nexport default __SENTRY__.withSentry(${state.optionsFn}, __SENTRY_DEFAULT_EXPORT__);\\n`);\n state.needsImport = true;\n state.autoWrapped.add(DEFAULT_EXPORT);\n}\n\nfunction handleNamedExport(node: ExportNamedNode, ctx: TransformContext, state: TransformState): void {\n const decl = node.declaration;\n\n // ---- Manually wrapped class export ----\n // `export const MyDO = instrumentDurableObjectWithSentry(...)` — count it\n // as wrapped so the plugin doesn't warn about it, but leave it alone.\n if (decl?.type === 'VariableDeclaration') {\n collectManuallyWrappedClassExports(decl, ctx, state);\n return;\n }\n\n // ---- Named class export matching a configured binding ----\n if (decl?.type === 'ClassDeclaration') {\n wrapInlineClassExport(node, decl, ctx, state);\n return;\n }\n\n // ---- Specifier export (`export { Foo as MyDO }`, `export { MyDO } from './do'`) ----\n wrapSpecifierExports(node, ctx, state);\n}\n\nfunction collectManuallyWrappedClassExports(\n varDecl: VariableDeclarationNode,\n ctx: TransformContext,\n state: TransformState,\n): void {\n for (const declarator of varDecl.declarations ?? []) {\n const name = declarator.id?.type === 'Identifier' ? declarator.id.name : undefined;\n const kind = name ? ctx.classWrappers.get(name) : undefined;\n if (!name || !kind || !declarator.init) continue;\n\n // A hand-wrapped Agent is configured as a Durable Object, so accept either helper there —\n // otherwise an already-instrumented Agent would be reported as unwrapped.\n const accepted =\n kind === 'durableObject' ? [WRAPPER_METHODS.durableObject, WRAPPER_METHODS.agent] : [WRAPPER_METHODS[kind]];\n\n if (accepted.some(method => isCallToMethod(declarator.init as BaseNode, method))) {\n state.wrappedClasses.add(name);\n }\n }\n}\n\nfunction wrapInlineClassExport(\n exportNode: ExportNamedNode,\n classDecl: ClassDeclarationNode,\n ctx: TransformContext,\n state: TransformState,\n): void {\n const classId = classDecl.id;\n // Inline export: the exported name and the local class name are the same.\n const kind = classId ? resolveWrapperKind(classId.name, classId.name, state) : undefined;\n if (!classId || !kind) return;\n\n const className = classId.name;\n\n // Strip the `export ` keyword\n state.ms.overwrite(exportNode.start, classDecl.start, '');\n\n const wrappedName = wrapLocalClass(className, classDecl, kind, state);\n state.ms.appendLeft(exportNode.end, `export { ${wrappedName} as ${className} };\\n`);\n\n state.wrappedClasses.add(className);\n state.autoWrapped.add(className);\n}\n\n/**\n * Wrap a class declared in this module and return the binding that holds the wrapper.\n *\n * The declaration is left exactly as written. Only the *export* has to become the wrapper, so the\n * wrapper gets its own binding and the export is aliased to it, the same shape as the documented\n * manual `instrument*WithSentry` pattern and the cross-module re-export path below. Renaming the\n * declaration instead (`class __SENTRY_ORIGINAL_MyAgent__`) would also rename what the class reports\n * as `Function.prototype.name`, which libraries read to identify the user's class: `@cloudflare/think`\n * hands `this.constructor.name` to the AI SDK as the telemetry `functionId`, and that surfaced as a\n * `gen_ai.invoke_agent __SENTRY_ORIGINAL_MyAgent__` span.\n */\nfunction wrapLocalClass(\n localName: string,\n localClass: ClassDeclarationNode,\n kind: ClassWrapperKind,\n state: TransformState,\n): string {\n const existing = state.wrappedLocals.get(localName);\n if (existing) return existing;\n\n const wrappedName = `__SENTRY_WRAPPED_${localName}__`;\n state.wrappedLocals.set(localName, wrappedName);\n state.ms.appendLeft(\n localClass.end,\n `\\nconst ${wrappedName} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${localName});\\n`,\n );\n state.needsImport = true;\n return wrappedName;\n}\n\n/**\n * Wrap the configured classes an `export { ... }` statement names.\n *\n * Each such specifier is re-pointed at a binding holding the wrapper, which means rebuilding the\n * statement; specifiers this plugin has no business touching are carried over verbatim. For a class\n * declared in this module the wrapper binding follows the declaration (see {@link wrapLocalClass}).\n * A class that lives in **another** module — imported and re-exported, or re-exported directly — is\n * first bound under a private name, since an import binding cannot be reassigned and the `from` form\n * has no local binding at all.\n */\nfunction wrapSpecifierExports(node: ExportNamedNode, ctx: TransformContext, state: TransformState): void {\n const specifiers = node.specifiers ?? [];\n if (specifiers.length === 0) return;\n\n const sourceLiteral = node.source ? state.ms.original.slice(node.source.start, node.source.end) : undefined;\n\n const prelude: string[] = [];\n const wrappedPairs: string[] = [];\n const kept: string[] = [];\n\n for (const specifier of specifiers) {\n const pair = wrapSpecifier(specifier, sourceLiteral, ctx, state, prelude);\n if (pair) {\n wrappedPairs.push(pair);\n } else {\n kept.push(state.ms.original.slice(specifier.start, specifier.end));\n }\n }\n\n if (wrappedPairs.length === 0) return;\n\n const statements = [...prelude, `export { ${wrappedPairs.join(', ')} };`];\n if (kept.length > 0) {\n const clause = `export { ${kept.join(', ')} }`;\n statements.push(sourceLiteral ? `${clause} from ${sourceLiteral};` : `${clause};`);\n }\n state.ms.overwrite(node.start, node.end, statements.join('\\n'));\n}\n\n/**\n * Handle one export specifier, returning the `Wrapped as Exported` pair to emit for a class that\n * gets wrapped. The import/wrapper statements a cross-module pair depends on are pushed onto\n * `prelude`; a local class's wrapper binding is emitted after its declaration instead.\n *\n * Returns `undefined` when the specifier can stay exactly as written: it doesn't name a configured\n * class, or the binding is already hand-wrapped.\n */\nfunction wrapSpecifier(\n specifier: ExportSpecifierNode,\n sourceLiteral: string | undefined,\n ctx: TransformContext,\n state: TransformState,\n prelude: string[],\n): string | undefined {\n const exportedName =\n specifier.type === 'ExportSpecifier' && specifier.exported?.type === 'Identifier'\n ? specifier.exported.name\n : undefined;\n const localName = specifier.local?.type === 'Identifier' ? specifier.local.name : undefined;\n // With a `from` clause the specifier names an export of the *source* module, not a binding here.\n const kind = exportedName\n ? resolveWrapperKind(exportedName, sourceLiteral ? undefined : localName, state)\n : undefined;\n\n if (!exportedName || !localName || !kind) return undefined;\n\n // Without a `from` clause the specifier points at a module-local binding.\n if (!sourceLiteral) {\n const localClass = state.topLevelClasses.get(localName);\n\n if (localClass?.id) {\n const wrappedName = wrapLocalClass(localName, localClass, kind, state);\n state.wrappedClasses.add(exportedName);\n return `${wrappedName} as ${exportedName}`;\n }\n\n if (state.manuallyWrappedLocals.has(localName)) {\n state.wrappedClasses.add(exportedName);\n return undefined;\n }\n }\n\n // The class comes from another module: bind it under a private name (for the `from` form, which\n // has no local binding at all), wrap that, and export the wrapper under the configured name.\n let target = localName;\n\n if (sourceLiteral) {\n target = `__SENTRY_REEXPORT_${exportedName}__`;\n prelude.push(\n localName === DEFAULT_IMPORT\n ? `import ${target} from ${sourceLiteral};`\n : `import { ${localName} as ${target} } from ${sourceLiteral};`,\n );\n }\n\n const wrappedName = `__SENTRY_WRAPPED_${exportedName}__`;\n\n // The class may already be hand-wrapped in its own module, which this transform cannot see. The\n // emitted guard returns such a class as-is instead of nesting a second wrapper around it.\n prelude.push(\n `const ${wrappedName} = __SENTRY__._INTERNAL_wrapUnlessInstrumented(__SENTRY__.${WRAPPER_METHODS[kind]}, ${state.optionsFn}, ${target});`,\n );\n state.wrappedClasses.add(exportedName);\n state.autoWrapped.add(exportedName);\n state.needsImport = true;\n\n return `${wrappedName} as ${exportedName}`;\n}\n"],"names":["MagicString","detectWorkerEntrypointClasses","DEFAULT_EXPORT","wrappedName"],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ const instrumentEnv = require('./instrumentations/worker/instrumentEnv.js');
|
|
|
10
10
|
const scopeUtils = require('./scope-utils.js');
|
|
11
11
|
const sdk = require('./sdk.js');
|
|
12
12
|
const instrumentContext = require('./utils/instrumentContext.js');
|
|
13
|
+
const invocationContext = require('./utils/invocationContext.js');
|
|
13
14
|
const invocationScope = require('./utils/invocationScope.js');
|
|
14
15
|
|
|
15
16
|
const UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i;
|
|
@@ -46,6 +47,10 @@ class WrappedWorkflowStep {
|
|
|
46
47
|
const hasStepContext = typeof attempt === "number" && typeof retryLimit === "number";
|
|
47
48
|
const isFinalAttempt = !hasStepContext || attempt > retryLimit;
|
|
48
49
|
return core.withIsolationScope(this._isolationScope, () => {
|
|
50
|
+
const invocationState = invocationContext.getInvocationState();
|
|
51
|
+
if (invocationState) {
|
|
52
|
+
invocationState.flushPointReached = false;
|
|
53
|
+
}
|
|
49
54
|
const stepResult = core.startSpan(
|
|
50
55
|
{
|
|
51
56
|
name,
|
|
@@ -79,11 +84,11 @@ class WrappedWorkflowStep {
|
|
|
79
84
|
);
|
|
80
85
|
return stepResult.then(
|
|
81
86
|
(result) => {
|
|
82
|
-
this._waitUntil(core.flush(2e3));
|
|
87
|
+
this._waitUntil(core.withScope(scopeForStep, () => core.flush(2e3)));
|
|
83
88
|
return result;
|
|
84
89
|
},
|
|
85
90
|
(error) => {
|
|
86
|
-
this._waitUntil(core.flush(2e3));
|
|
91
|
+
this._waitUntil(core.withScope(scopeForStep, () => core.flush(2e3)));
|
|
87
92
|
throw error;
|
|
88
93
|
}
|
|
89
94
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.js","sources":["../../../src/workflows.ts"],"sourcesContent":["import { SENTRY_SEGMENT_NAME_SOURCE, CODE_FUNCTION_NAME, SENTRY_OP } from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport type { PropagationContext, Scope } from '@sentry/core';\nimport {\n captureException,\n flush,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type {\n WorkflowDelayDuration,\n WorkflowEntrypoint,\n WorkflowEvent,\n WorkflowSleepDuration,\n WorkflowStep,\n WorkflowStepConfig,\n WorkflowStepContext,\n WorkflowStepEvent,\n WorkflowStepRollbackOptions,\n WorkflowTimeoutDuration,\n} from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils/no-diagnostic-channels';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { markAsInstrumented } from './instrument';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { addCloudResourceContext } from './scope-utils';\nimport { init } from './sdk';\nimport { instrumentContext } from './utils/instrumentContext';\nimport type { DefaultEnv, ResolveEnv, StrictCloudflareOptions } from './types';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\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\n/**\n * Hashes a string to a UUID using SHA-1.\n */\nexport async function deterministicTraceIdFromInstanceId(instanceId: string): Promise<string> {\n const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(instanceId));\n return (\n Array.from(new Uint8Array(buf))\n // We only need the first 16 bytes for the 32 characters\n .slice(0, 16)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n );\n}\n\nasync function propagationContextFromInstanceId(instanceId: string): Promise<PropagationContext> {\n const traceId = UUID_REGEX.test(instanceId)\n ? instanceId.replace(/-/g, '')\n : await deterministicTraceIdFromInstanceId(instanceId);\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\nclass WrappedWorkflowStep implements WorkflowStep {\n public constructor(\n private _instanceId: string,\n private _options: CloudflareOptions,\n private _step: WorkflowStep,\n private _waitUntil: ExecutionContext['waitUntil'],\n private _isolationScope: Scope,\n ) {}\n\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n callback: (ctx: WorkflowStepContext) => Promise<T>,\n rollbackOptions?: WorkflowStepRollbackOptions<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>, const C extends WorkflowStepConfig>(\n name: string,\n config: C,\n callback: (\n ctx: WorkflowStepContext<C['retries'] extends { delay: infer D } ? D : WorkflowDelayDuration | number>,\n ) => Promise<T>,\n rollbackOptions?: WorkflowStepRollbackOptions<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n configOrCallback: WorkflowStepConfig | ((ctx: WorkflowStepContext) => Promise<T>),\n callbackOrRollback?: ((ctx: WorkflowStepContext) => Promise<T>) | WorkflowStepRollbackOptions<T>,\n maybeRollback?: WorkflowStepRollbackOptions<T>,\n ): Promise<T> {\n // Capture the current scope, so parent span (e.g., a startSpan surrounding step.do) is preserved\n const scopeForStep = getCurrentScope();\n\n const hasConfig = typeof configOrCallback !== 'function';\n const config = hasConfig ? configOrCallback : undefined;\n const userCallback = (hasConfig ? callbackOrRollback : configOrCallback) as (\n ctx: WorkflowStepContext,\n ) => Promise<T>;\n const rollbackOptions = (hasConfig ? maybeRollback : callbackOrRollback) as\n | WorkflowStepRollbackOptions<T>\n | undefined;\n\n const instrumentedCallback = async (...args: unknown[]): Promise<T> => {\n // Feature detection: Cloudflare Workflows (April 2026+) pass a step context\n // with `attempt` and `config.retries.limit`. When available, we only capture\n // errors on the final attempt to avoid duplicates during retries.\n const stepContext = args[0] as { attempt?: number; config?: { retries?: { limit?: number } } } | undefined;\n const attempt = stepContext?.attempt;\n const retryLimit = stepContext?.config?.retries?.limit;\n const hasStepContext = typeof attempt === 'number' && typeof retryLimit === 'number';\n\n // Only capture error on final attempt (attempt > retryLimit means no more retries left)\n // or when step context is unavailable (legacy behavior - capture all errors)\n const isFinalAttempt = !hasStepContext || attempt > retryLimit;\n\n // The engine invokes step callbacks outside the async context of `run`, so the\n // run's isolation scope (and with it the invocation state that ties eager sends\n // to this invocation's `waitUntil`) has to be restored explicitly.\n return withIsolationScope(this._isolationScope, () => {\n const stepResult = startSpan(\n {\n name,\n scope: scopeForStep,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: name,\n 'workflow.step.name': name,\n 'cloudflare.workflow.timeout': config?.timeout,\n 'cloudflare.workflow.retries.backoff': config?.retries?.backoff,\n // In workers-types v5, `delay` may be a `WorkflowDelayFunction`, which isn't a valid span attribute value.\n 'cloudflare.workflow.retries.delay':\n typeof config?.retries?.delay === 'function' ? undefined : config?.retries?.delay,\n 'cloudflare.workflow.retries.limit': config?.retries?.limit,\n 'cloudflare.workflow.attempt': attempt,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'task',\n },\n },\n async span => {\n try {\n const result = await (userCallback as (...args: unknown[]) => Promise<T>)(...args);\n span.setStatus({ code: 1 });\n return result;\n } catch (error) {\n if (isFinalAttempt) {\n captureException(error, { mechanism: { handled: true, type: 'auto.faas.cloudflare.workflow' } });\n }\n throw error;\n }\n },\n );\n // Deliver after the step span has ended, so the span rides this flush instead of\n // starting an eager drain (same ordering as `wrapMethodWithSentry`'s teardown).\n return stepResult.then(\n result => {\n this._waitUntil(flush(2000));\n return result;\n },\n error => {\n this._waitUntil(flush(2000));\n throw error;\n },\n );\n });\n };\n\n if (config) {\n return rollbackOptions\n ? this._step.do(name, config, instrumentedCallback, rollbackOptions)\n : this._step.do(name, config, instrumentedCallback);\n }\n\n return rollbackOptions\n ? this._step.do(name, instrumentedCallback, rollbackOptions)\n : 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 = DefaultEnv, // Environment type\n P = unknown, // Payload type\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends WorkflowEntrypoint<any, any> = WorkflowEntrypoint<E, P>, // WorkflowEntrypoint type\n // The constraint must not route through `T`: workers-types defaults `WorkflowEntrypoint`'s\n // `Env` to `unknown` (unlike `WorkerEntrypoint`/`DurableObject`, which default to\n // `Cloudflare.Env`), so a bare subclass would be rejected in a `wrangler types` project.\n // The callback env is resolved from the inferred constructor via `ResolveEnv` instead.\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (ctx: ExecutionContext, env: any) => WorkflowEntrypoint<any, any> = new (\n ctx: ExecutionContext,\n // oxlint-disable-next-line typescript/no-explicit-any\n env: any,\n ) => T, // Constructor type of the WorkflowEntrypoint class\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, E>) => StrictCloudflareOptions<O>, WorkFlowClass: C): C {\n const InstrumentedClass = new Proxy(WorkFlowClass, {\n // oxlint-disable-next-line typescript/no-explicit-any\n construct(target: C, args: [ctx: ExecutionContext, env: any], newTarget) {\n const [ctx, env] = args;\n const context = instrumentContext(ctx);\n const options = optionsCallback(env);\n args[0] = context;\n args[1] = instrumentEnv(env as Record<string, unknown>, options) as E;\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 setAsyncLocalStorageAsyncContextStrategy();\n\n return withInvocationIsolationScope(async isolationScope => {\n const waitUntil = getOriginalWaitUntil(context).bind(context);\n const client = init({ ...options, ctx: context, enableDedupe: false });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return withScope(async scope => {\n const propagationContext = await propagationContextFromInstanceId(event.instanceId);\n scope.setPropagationContext(propagationContext);\n\n try {\n return await obj.run.call(\n obj,\n event,\n new WrappedWorkflowStep(event.instanceId, options, step, waitUntil, isolationScope),\n );\n } finally {\n waitUntil(flushAndDispose(client));\n }\n });\n }, context);\n };\n }\n return Reflect.get(obj, prop, receiver);\n },\n });\n },\n });\n // Recognizable for `_INTERNAL_wrapUnlessInstrumented`, so auto-instrumentation never nests wrappers.\n markAsInstrumented(InstrumentedClass);\n return InstrumentedClass;\n}\n"],"names":["getCurrentScope","withIsolationScope","startSpan","SENTRY_OP","FUNCTION","CODE_FUNCTION_NAME","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","captureException","flush","instrumentContext","instrumentEnv","setAsyncLocalStorageAsyncContextStrategy","withInvocationIsolationScope","getOriginalWaitUntil","init","addCloudResourceContext","withScope","flushAndDispose","markAsInstrumented"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workflows.js","sources":["../../../src/workflows.ts"],"sourcesContent":["import { SENTRY_SEGMENT_NAME_SOURCE, CODE_FUNCTION_NAME, SENTRY_OP } from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport type { PropagationContext, Scope } from '@sentry/core';\nimport {\n captureException,\n flush,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type {\n WorkflowDelayDuration,\n WorkflowEntrypoint,\n WorkflowEvent,\n WorkflowSleepDuration,\n WorkflowStep,\n WorkflowStepConfig,\n WorkflowStepContext,\n WorkflowStepEvent,\n WorkflowStepRollbackOptions,\n WorkflowTimeoutDuration,\n} from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils/no-diagnostic-channels';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { markAsInstrumented } from './instrument';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { addCloudResourceContext } from './scope-utils';\nimport { init } from './sdk';\nimport { instrumentContext } from './utils/instrumentContext';\nimport type { DefaultEnv, ResolveEnv, StrictCloudflareOptions } from './types';\nimport { getInvocationState } from './utils/invocationContext';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\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\n/**\n * Hashes a string to a UUID using SHA-1.\n */\nexport async function deterministicTraceIdFromInstanceId(instanceId: string): Promise<string> {\n const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(instanceId));\n return (\n Array.from(new Uint8Array(buf))\n // We only need the first 16 bytes for the 32 characters\n .slice(0, 16)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n );\n}\n\nasync function propagationContextFromInstanceId(instanceId: string): Promise<PropagationContext> {\n const traceId = UUID_REGEX.test(instanceId)\n ? instanceId.replace(/-/g, '')\n : await deterministicTraceIdFromInstanceId(instanceId);\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\nclass WrappedWorkflowStep implements WorkflowStep {\n public constructor(\n private _instanceId: string,\n private _options: CloudflareOptions,\n private _step: WorkflowStep,\n private _waitUntil: ExecutionContext['waitUntil'],\n private _isolationScope: Scope,\n ) {}\n\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n callback: (ctx: WorkflowStepContext) => Promise<T>,\n rollbackOptions?: WorkflowStepRollbackOptions<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>, const C extends WorkflowStepConfig>(\n name: string,\n config: C,\n callback: (\n ctx: WorkflowStepContext<C['retries'] extends { delay: infer D } ? D : WorkflowDelayDuration | number>,\n ) => Promise<T>,\n rollbackOptions?: WorkflowStepRollbackOptions<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n configOrCallback: WorkflowStepConfig | ((ctx: WorkflowStepContext) => Promise<T>),\n callbackOrRollback?: ((ctx: WorkflowStepContext) => Promise<T>) | WorkflowStepRollbackOptions<T>,\n maybeRollback?: WorkflowStepRollbackOptions<T>,\n ): Promise<T> {\n // Capture the current scope, so parent span (e.g., a startSpan surrounding step.do) is preserved\n const scopeForStep = getCurrentScope();\n\n const hasConfig = typeof configOrCallback !== 'function';\n const config = hasConfig ? configOrCallback : undefined;\n const userCallback = (hasConfig ? callbackOrRollback : configOrCallback) as (\n ctx: WorkflowStepContext,\n ) => Promise<T>;\n const rollbackOptions = (hasConfig ? maybeRollback : callbackOrRollback) as\n | WorkflowStepRollbackOptions<T>\n | undefined;\n\n const instrumentedCallback = async (...args: unknown[]): Promise<T> => {\n // Feature detection: Cloudflare Workflows (April 2026+) pass a step context\n // with `attempt` and `config.retries.limit`. When available, we only capture\n // errors on the final attempt to avoid duplicates during retries.\n const stepContext = args[0] as { attempt?: number; config?: { retries?: { limit?: number } } } | undefined;\n const attempt = stepContext?.attempt;\n const retryLimit = stepContext?.config?.retries?.limit;\n const hasStepContext = typeof attempt === 'number' && typeof retryLimit === 'number';\n\n // Only capture error on final attempt (attempt > retryLimit means no more retries left)\n // or when step context is unavailable (legacy behavior - capture all errors)\n const isFinalAttempt = !hasStepContext || attempt > retryLimit;\n\n // The engine invokes step callbacks outside the async context of `run`, so the\n // run's isolation scope (and with it the invocation state that ties eager sends\n // to this invocation's `waitUntil`) has to be restored explicitly.\n return withIsolationScope(this._isolationScope, () => {\n const invocationState = getInvocationState();\n\n if (invocationState) {\n invocationState.flushPointReached = false;\n }\n\n const stepResult = startSpan(\n {\n name,\n scope: scopeForStep,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: name,\n 'workflow.step.name': name,\n 'cloudflare.workflow.timeout': config?.timeout,\n 'cloudflare.workflow.retries.backoff': config?.retries?.backoff,\n // In workers-types v5, `delay` may be a `WorkflowDelayFunction`, which isn't a valid span attribute value.\n 'cloudflare.workflow.retries.delay':\n typeof config?.retries?.delay === 'function' ? undefined : config?.retries?.delay,\n 'cloudflare.workflow.retries.limit': config?.retries?.limit,\n 'cloudflare.workflow.attempt': attempt,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'task',\n },\n },\n async span => {\n try {\n const result = await (userCallback as (...args: unknown[]) => Promise<T>)(...args);\n span.setStatus({ code: 1 });\n return result;\n } catch (error) {\n if (isFinalAttempt) {\n captureException(error, { mechanism: { handled: true, type: 'auto.faas.cloudflare.workflow' } });\n }\n throw error;\n }\n },\n );\n // Deliver after the step span has ended, so the span rides this flush instead of\n // starting an eager drain (same ordering as `wrapMethodWithSentry`'s teardown). The flush runs on the\n // step's scope: the engine calls the step callback outside of `run()`, so the current scope here has\n // neither the client nor the run's trace, and envelopes without a DSC are dropped by Relay.\n return stepResult.then(\n result => {\n this._waitUntil(withScope(scopeForStep, () => flush(2000)));\n return result;\n },\n error => {\n this._waitUntil(withScope(scopeForStep, () => flush(2000)));\n throw error;\n },\n );\n });\n };\n\n if (config) {\n return rollbackOptions\n ? this._step.do(name, config, instrumentedCallback, rollbackOptions)\n : this._step.do(name, config, instrumentedCallback);\n }\n\n return rollbackOptions\n ? this._step.do(name, instrumentedCallback, rollbackOptions)\n : 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 = DefaultEnv, // Environment type\n P = unknown, // Payload type\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends WorkflowEntrypoint<any, any> = WorkflowEntrypoint<E, P>, // WorkflowEntrypoint type\n // The constraint must not route through `T`: workers-types defaults `WorkflowEntrypoint`'s\n // `Env` to `unknown` (unlike `WorkerEntrypoint`/`DurableObject`, which default to\n // `Cloudflare.Env`), so a bare subclass would be rejected in a `wrangler types` project.\n // The callback env is resolved from the inferred constructor via `ResolveEnv` instead.\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (ctx: ExecutionContext, env: any) => WorkflowEntrypoint<any, any> = new (\n ctx: ExecutionContext,\n // oxlint-disable-next-line typescript/no-explicit-any\n env: any,\n ) => T, // Constructor type of the WorkflowEntrypoint class\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, E>) => StrictCloudflareOptions<O>, WorkFlowClass: C): C {\n const InstrumentedClass = new Proxy(WorkFlowClass, {\n // oxlint-disable-next-line typescript/no-explicit-any\n construct(target: C, args: [ctx: ExecutionContext, env: any], newTarget) {\n const [ctx, env] = args;\n const context = instrumentContext(ctx);\n const options = optionsCallback(env);\n args[0] = context;\n args[1] = instrumentEnv(env as Record<string, unknown>, options) as E;\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 setAsyncLocalStorageAsyncContextStrategy();\n\n return withInvocationIsolationScope(async isolationScope => {\n const waitUntil = getOriginalWaitUntil(context).bind(context);\n const client = init({ ...options, ctx: context, enableDedupe: false });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return withScope(async scope => {\n const propagationContext = await propagationContextFromInstanceId(event.instanceId);\n scope.setPropagationContext(propagationContext);\n\n try {\n return await obj.run.call(\n obj,\n event,\n new WrappedWorkflowStep(event.instanceId, options, step, waitUntil, isolationScope),\n );\n } finally {\n waitUntil(flushAndDispose(client));\n }\n });\n }, context);\n };\n }\n return Reflect.get(obj, prop, receiver);\n },\n });\n },\n });\n // Recognizable for `_INTERNAL_wrapUnlessInstrumented`, so auto-instrumentation never nests wrappers.\n markAsInstrumented(InstrumentedClass);\n return InstrumentedClass;\n}\n"],"names":["getCurrentScope","withIsolationScope","getInvocationState","startSpan","SENTRY_OP","FUNCTION","CODE_FUNCTION_NAME","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","captureException","withScope","flush","instrumentContext","instrumentEnv","setAsyncLocalStorageAsyncContextStrategy","withInvocationIsolationScope","getOriginalWaitUntil","init","addCloudResourceContext","flushAndDispose","markAsInstrumented"],"mappings":"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"}
|
package/build/esm/dev/client.js
CHANGED
|
@@ -59,16 +59,23 @@ class CloudflareClient extends ServerRuntimeClient {
|
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Flushes pending operations and ensures all data is processed.
|
|
62
|
-
* If a timeout is provided, the operation will be completed within the specified time limit.
|
|
63
62
|
*
|
|
64
|
-
*
|
|
63
|
+
* Each phase waits at most `timeout`: the flush lock of a per-invocation client, pending spans, event
|
|
64
|
+
* processing and the transport drain. So a flush can take a small multiple of `timeout`, which stays well
|
|
65
|
+
* below Cloudflare's 30 second `waitUntil` limit for the timeouts the SDK uses. Sends still pending when
|
|
66
|
+
* the drain times out are aborted.
|
|
65
67
|
*
|
|
66
|
-
* @param {number} [timeout] -
|
|
68
|
+
* @param {number} [timeout] - Maximum time in milliseconds for each phase of the flush.
|
|
67
69
|
* @return {Promise<boolean>} A promise that resolves to a boolean indicating whether the flush operation was successful.
|
|
68
70
|
*/
|
|
69
71
|
async flush(timeout) {
|
|
70
72
|
if (this._flushLock) {
|
|
71
|
-
|
|
73
|
+
let timer;
|
|
74
|
+
await Promise.race([
|
|
75
|
+
this._flushLock.finalize(),
|
|
76
|
+
...timeout ? [new Promise((resolve) => timer = setTimeout(resolve, timeout))] : []
|
|
77
|
+
]);
|
|
78
|
+
clearTimeout(timer);
|
|
72
79
|
}
|
|
73
80
|
if (this._pendingSpans.size > 0 && this._spanCompletionPromise) {
|
|
74
81
|
DEBUG_BUILD && debug.log("[CloudflareClient] Waiting for", this._pendingSpans.size, "pending spans to complete...");
|