{"version":3,"file":"workerEntrypoint.js","sources":["../../../src/vite/workerEntrypoint.ts"],"sourcesContent":["import type { BaseNode, ProgramBody } from './transform';\n\n// ---------------------------------------------------------------------------\n// Minimal ESTree node shapes for structural WorkerEntrypoint detection.\n// ---------------------------------------------------------------------------\n\ninterface IdentifierNode extends BaseNode {\n name: string;\n}\n\ninterface MemberExpressionNode extends BaseNode {\n object?: { type: string; name?: string };\n property?: { type: string; name?: string };\n}\n\ninterface ClassDeclarationNode extends BaseNode {\n id?: IdentifierNode | null;\n superClass?: BaseNode | null;\n}\n\ninterface ExportNamedDeclNode extends BaseNode {\n declaration?: BaseNode | null;\n}\n\ninterface ImportSpecifierNode {\n type: string;\n imported?: { type: string; name?: string };\n local?: { type: string; name?: string };\n}\n\ninterface ImportDeclarationNode extends BaseNode {\n source?: { value?: unknown };\n specifiers?: ImportSpecifierNode[];\n}\n\ninterface WorkerEntrypointBases {\n /** Local identifiers bound to the named `WorkerEntrypoint` import. */\n named: Set;\n /** Local identifiers bound to a `* as ns` import of `cloudflare:workers`. */\n namespaces: Set;\n}\n\n/**\n * Find top-level classes that (transitively, within this module) extend\n * `WorkerEntrypoint` imported from `cloudflare:workers`. esbuild has already\n * stripped TypeScript by transform time, so a superclass is a plain identifier\n * (`extends WorkerEntrypoint`) or member access (`extends cf.WorkerEntrypoint`).\n *\n * Only same-file base chains are resolvable here; a base class imported from\n * another module is invisible and relies on the config self-binding fallback.\n */\nexport function detectWorkerEntrypointClasses(ast: ProgramBody): Set {\n const bases = collectWorkerEntrypointImports(ast);\n if (bases.named.size === 0 && bases.namespaces.size === 0) {\n return new Set();\n }\n\n // Every top-level class, including the `export class Foo {}` form (where the\n // class is nested inside an ExportNamedDeclaration) so directly-exported\n // entrypoints are seen too.\n const classes = new Map();\n for (const node of ast.body) {\n const classNode = asClassDeclaration(node);\n if (classNode?.id?.name) classes.set(classNode.id.name, classNode);\n }\n\n const entrypoints = new Set();\n // Iterate to a fixed point so an indirect chain (A extends B extends WE) is\n // fully resolved regardless of declaration order.\n let changed = true;\n while (changed) {\n changed = false;\n for (const [name, classNode] of classes) {\n if (entrypoints.has(name)) continue;\n if (extendsWorkerEntrypoint(classNode.superClass, bases, entrypoints)) {\n entrypoints.add(name);\n changed = true;\n }\n }\n }\n return entrypoints;\n}\n\n/** Unwrap `export class Foo {}` to its ClassDeclaration; pass bare classes through. */\nfunction asClassDeclaration(node: BaseNode): ClassDeclarationNode | undefined {\n if (node.type === 'ClassDeclaration') return node as ClassDeclarationNode;\n if (node.type === 'ExportNamedDeclaration') {\n const decl = (node as ExportNamedDeclNode).declaration;\n if (decl?.type === 'ClassDeclaration') return decl as ClassDeclarationNode;\n }\n return undefined;\n}\n\nfunction collectWorkerEntrypointImports(ast: ProgramBody): WorkerEntrypointBases {\n const named = new Set();\n const namespaces = new Set();\n for (const node of ast.body) {\n if (node.type !== 'ImportDeclaration') continue;\n const importNode = node as ImportDeclarationNode;\n if (importNode.source?.value !== 'cloudflare:workers') continue;\n for (const specifier of importNode.specifiers ?? []) {\n if (\n specifier.type === 'ImportSpecifier' &&\n specifier.imported?.name === 'WorkerEntrypoint' &&\n specifier.local?.name\n ) {\n named.add(specifier.local.name);\n } else if (specifier.type === 'ImportNamespaceSpecifier' && specifier.local?.name) {\n namespaces.add(specifier.local.name);\n }\n }\n }\n return { named, namespaces };\n}\n\n/**\n * Whether a superclass expression resolves to `WorkerEntrypoint` — either a bare\n * identifier from the named import (or an already-detected local subclass), or a\n * `ns.WorkerEntrypoint` member access off a namespace import.\n */\nfunction extendsWorkerEntrypoint(\n superClass: BaseNode | null | undefined,\n bases: WorkerEntrypointBases,\n detected: Set,\n): boolean {\n if (!superClass) return false;\n if (superClass.type === 'Identifier') {\n const name = (superClass as IdentifierNode).name;\n return bases.named.has(name) || detected.has(name);\n }\n if (superClass.type === 'MemberExpression') {\n const member = superClass as MemberExpressionNode;\n return (\n member.object?.type === 'Identifier' &&\n !!member.object.name &&\n bases.namespaces.has(member.object.name) &&\n member.property?.name === 'WorkerEntrypoint'\n );\n }\n return false;\n}\n"],"names":[],"mappings":"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"}