Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const MagicString = require('magic-string'); const bindings = require('./bindings.js'); const workerEntrypoint = require('./workerEntrypoint.js'); const MERGED_OPTIONS_IDENTIFIER = "__SENTRY_OPTIONS__"; function isCallToMethod(node, methodName) { if (node.type !== "CallExpression") return false; const callee = node.callee; if (!callee) return false; if (callee.type === "Identifier" && callee.name === methodName) return true; return callee.type === "MemberExpression" && callee.property?.type === "Identifier" && callee.property.name === methodName; } const DEFAULT_IMPORT = "default"; const WRAPPER_METHODS = { durableObject: "instrumentDurableObjectWithSentry", agent: "instrumentAgentWithSentry", workflow: "instrumentWorkflowWithSentry", workerEntrypoint: "withSentry" }; function applyAutoInstrumentTransforms(code, ast, ctx) { const ms = new MagicString.default(code); const topLevelClasses = collectTopLevelClasses(ast); const sameWorkerBindings = ctx.sameWorkerBindings ?? []; const state = { ms, needsImport: false, wrappedClasses: /* @__PURE__ */ new Set(), topLevelClasses, renamedLocals: /* @__PURE__ */ new Set(), classWrappers: ctx.classWrappers, agentClasses: ctx.agentClasses ?? /* @__PURE__ */ new Set(), workerEntrypointClasses: workerEntrypoint.detectWorkerEntrypointClasses(ast), // The identifier must be chosen before wrapping, which bindings survive is only known after. optionsFn: sameWorkerBindings.length > 0 ? MERGED_OPTIONS_IDENTIFIER : ctx.optionsFn, autoWrapped: /* @__PURE__ */ new Set(), manuallyWrappedLocals: collectManuallyWrappedLocals(ast) }; const { wrappedClasses } = state; for (const node of ast.body) { if (node.type === "ExportNamedDeclaration") { handleNamedExport(node, ctx, state); } } for (const node of ast.body) { if (node.type === "ExportDefaultDeclaration") { wrapDefaultExport(node, ctx, state); } } if (!state.needsImport) { if (wrappedClasses.size === 0) return void 0; return { code, map: ms.generateMap({ hires: true }), wrappedClasses }; } if (sameWorkerBindings.length > 0) { ms.prepend(buildMergedOptionsDeclaration(sameWorkerBindings, ctx.optionsFn, state)); } if (ctx.optionsImport) ms.prepend(ctx.optionsImport); ms.prepend("import * as __SENTRY__ from '@sentry/cloudflare';\n"); return { code: ms.toString(), map: ms.generateMap({ hires: true }), wrappedClasses }; } function buildMergedOptionsDeclaration(sameWorkerBindings, optionsFn, state) { const bindingNames = sameWorkerBindings.filter(({ className }) => state.autoWrapped.has(className)).map(({ bindingName }) => bindingName); if (!bindingNames.length) { return `const ${MERGED_OPTIONS_IDENTIFIER} = ${optionsFn}; `; } const names = bindingNames.map((name) => JSON.stringify(name)).join(", "); return `const ${MERGED_OPTIONS_IDENTIFIER} = (env) => { const opts = (${optionsFn})(env); return { ...opts, enableRpcTracePropagation: opts?.enableRpcTracePropagation ?? true, rpcTracePropagationBindings: [${names}, ...(opts?.rpcTracePropagationBindings ?? [])] }; }; `; } function resolveWrapperKind(exportedName, localName, state) { const configured = state.classWrappers.get(exportedName); if (configured === "durableObject" && (localName && state.agentClasses.has(localName) || state.agentClasses.has(exportedName))) { return "agent"; } if (configured) return configured; if (localName && state.workerEntrypointClasses.has(localName)) return "workerEntrypoint"; return void 0; } function collectManuallyWrappedLocals(ast) { const wrapperMethods = Object.values(WRAPPER_METHODS); const locals = /* @__PURE__ */ new Set(); for (const node of ast.body) { if (node.type !== "VariableDeclaration") continue; for (const declarator of node.declarations ?? []) { const name = declarator.id?.type === "Identifier" ? declarator.id.name : void 0; const init = declarator.init; if (name && init && wrapperMethods.some((method) => isCallToMethod(init, method))) { locals.add(name); } } } return locals; } function collectTopLevelClasses(ast) { const classes = /* @__PURE__ */ new Map(); for (const node of ast.body) { if (node.type !== "ClassDeclaration") continue; const classNode = node; if (classNode.id?.name) classes.set(classNode.id.name, classNode); } return classes; } function wrapDefaultExport(node, ctx, state) { const decl = node.declaration; if (isCallToMethod(decl, "withSentry")) return; if (decl.type === "Identifier" && state.renamedLocals.has(decl.name)) { state.autoWrapped.add(bindings.DEFAULT_EXPORT); return; } state.ms.overwrite(node.start, decl.start, "const __SENTRY_DEFAULT_EXPORT__ = "); state.ms.append(` export default __SENTRY__.withSentry(${state.optionsFn}, __SENTRY_DEFAULT_EXPORT__); `); state.needsImport = true; state.autoWrapped.add(bindings.DEFAULT_EXPORT); } function handleNamedExport(node, ctx, state) { const decl = node.declaration; if (decl?.type === "VariableDeclaration") { collectManuallyWrappedClassExports(decl, ctx, state); return; } if (decl?.type === "ClassDeclaration") { wrapInlineClassExport(node, decl, ctx, state); return; } wrapSpecifierExports(node, ctx, state); } function collectManuallyWrappedClassExports(varDecl, ctx, state) { for (const declarator of varDecl.declarations ?? []) { const name = declarator.id?.type === "Identifier" ? declarator.id.name : void 0; const kind = name ? ctx.classWrappers.get(name) : void 0; if (!name || !kind || !declarator.init) continue; const accepted = kind === "durableObject" ? [WRAPPER_METHODS.durableObject, WRAPPER_METHODS.agent] : [WRAPPER_METHODS[kind]]; if (accepted.some((method) => isCallToMethod(declarator.init, method))) { state.wrappedClasses.add(name); } } } function wrapInlineClassExport(exportNode, classDecl, ctx, state) { const classId = classDecl.id; const kind = classId ? resolveWrapperKind(classId.name, classId.name, state) : void 0; if (!classId || !kind) return; const className = classId.name; const renamedClass = `__SENTRY_ORIGINAL_${className}__`; state.ms.overwrite(exportNode.start, classDecl.start, ""); state.ms.overwrite(classId.start, classId.end, renamedClass); state.ms.appendLeft( exportNode.end, ` export const ${className} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass}); ` ); state.wrappedClasses.add(className); state.autoWrapped.add(className); state.renamedLocals.add(className); state.needsImport = true; } function wrapSpecifierExports(node, ctx, state) { const specifiers = node.specifiers ?? []; if (specifiers.length === 0) return; const sourceLiteral = node.source ? state.ms.original.slice(node.source.start, node.source.end) : void 0; const prelude = []; const wrappedPairs = []; const kept = []; for (const specifier of specifiers) { const pair = wrapCrossModuleSpecifier(specifier, sourceLiteral, ctx, state, prelude); if (pair) { wrappedPairs.push(pair); } else { kept.push(state.ms.original.slice(specifier.start, specifier.end)); } } if (wrappedPairs.length === 0) return; const statements = [...prelude, `export { ${wrappedPairs.join(", ")} };`]; if (kept.length > 0) { const clause = `export { ${kept.join(", ")} }`; statements.push(sourceLiteral ? `${clause} from ${sourceLiteral};` : `${clause};`); } state.ms.overwrite(node.start, node.end, statements.join("\n")); } function wrapCrossModuleSpecifier(specifier, sourceLiteral, ctx, state, prelude) { const exportedName = specifier.type === "ExportSpecifier" && specifier.exported?.type === "Identifier" ? specifier.exported.name : void 0; const localName = specifier.local?.type === "Identifier" ? specifier.local.name : void 0; const kind = exportedName ? resolveWrapperKind(exportedName, sourceLiteral ? void 0 : localName, state) : void 0; if (!exportedName || !localName || !kind) return void 0; if (!sourceLiteral) { const localClass = state.topLevelClasses.get(localName); if (localClass?.id) { wrapLocalClassExport(localName, localClass, kind, ctx, state); state.wrappedClasses.add(exportedName); state.needsImport = true; return void 0; } if (state.manuallyWrappedLocals.has(localName)) { state.wrappedClasses.add(exportedName); return void 0; } } let target = localName; if (sourceLiteral) { target = `__SENTRY_REEXPORT_${exportedName}__`; prelude.push( localName === DEFAULT_IMPORT ? `import ${target} from ${sourceLiteral};` : `import { ${localName} as ${target} } from ${sourceLiteral};` ); } const wrappedName = `__SENTRY_WRAPPED_${exportedName}__`; prelude.push( `const ${wrappedName} = __SENTRY__._INTERNAL_wrapUnlessInstrumented(__SENTRY__.${WRAPPER_METHODS[kind]}, ${state.optionsFn}, ${target});` ); state.wrappedClasses.add(exportedName); state.autoWrapped.add(exportedName); state.needsImport = true; return `${wrappedName} as ${exportedName}`; } function wrapLocalClassExport(localName, localClass, kind, ctx, state) { const classId = localClass.id; if (!classId || state.renamedLocals.has(localName)) return; state.renamedLocals.add(localName); const renamedClass = `__SENTRY_ORIGINAL_${localName}__`; state.ms.overwrite(classId.start, classId.end, renamedClass); state.ms.appendLeft( localClass.end, ` const ${localName} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass}); ` ); } exports.applyAutoInstrumentTransforms = applyAutoInstrumentTransforms; //# sourceMappingURL=transform.js.map