{"version":3,"file":"ast.cjs","names":[],"sources":["../../src/ast.ts"],"sourcesContent":["import { parse } from '@babel/parser'\nimport _generate from '@babel/generator'\nimport * as t from '@babel/types'\nimport {\n  deadCodeElimination as _deadCodeElimination,\n  findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport type { GeneratorOptions, GeneratorResult } from '@babel/generator'\nimport type { ParseResult, ParserOptions } from '@babel/parser'\nimport type * as _babel_types from '@babel/types'\n\nexport type ParseAstOptions = ParserOptions & {\n  code: string\n}\n\nexport type ParseAstResult = ParseResult<_babel_types.File>\nexport function parseAst({ code, ...opts }: ParseAstOptions): ParseAstResult {\n  return parse(code, {\n    plugins: [\n      'jsx',\n      'typescript',\n      'explicitResourceManagement',\n      'importAttributes',\n      'deprecatedImportAssert',\n      ['decorators', { decoratorsBeforeExport: true }],\n      'decoratorAutoAccessors',\n    ],\n    sourceType: 'module',\n    ...opts,\n  })\n}\n\nlet generate = _generate\n\nif ('default' in generate) {\n  generate = generate.default as typeof generate\n}\ntype GenerateFromAstOptions = GeneratorOptions &\n  Required<Pick<GeneratorOptions, 'sourceFileName' | 'filename'>>\nexport function generateFromAst(\n  ast: _babel_types.Node,\n  opts?: GenerateFromAstOptions,\n): GeneratorResult {\n  return generate(\n    ast,\n    opts\n      ? { importAttributesKeyword: 'with', sourceMaps: true, ...opts }\n      : undefined,\n  )\n}\nexport type { GeneratorResult } from '@babel/generator'\n\n/**\n * Strips TypeScript type-only exports and imports from an AST.\n *\n * This is necessary because babel-dead-code-elimination doesn't handle\n * TypeScript type exports/imports. When a type export references an import\n * that pulls in server-only code, the dead code elimination won't remove\n * that import because it sees the type as still referencing it.\n *\n * This function removes:\n * - `export type Foo = ...`\n * - `export interface Foo { ... }`\n * - `export type { Foo } from './module'`\n * - `export type * from './module'`\n * - Type specifiers in mixed exports: `export { value, type Foo }` -> `export { value }`\n * - `import type { Foo } from './module'`\n * - Type specifiers in mixed imports: `import { value, type Foo } from './module'` -> `import { value }`\n *\n * Note: Non-exported type/interface declarations are preserved as they may be\n * used as type annotations within the code.\n *\n * @param ast - The Babel AST (or ParseResult) to mutate\n */\nexport function stripTypeExports(ast: ParseResult<_babel_types.File>): void {\n  // Filter the program body to remove type-only nodes\n  ast.program.body = ast.program.body.filter((node) => {\n    // Handle export declarations\n    if (t.isExportNamedDeclaration(node)) {\n      // Remove entire export if it's a type-only export\n      // e.g., `export type Foo = string`, `export interface Bar {}`, `export type { X } from './y'`\n      if (node.exportKind === 'type') {\n        return false\n      }\n\n      // For value exports with mixed specifiers, filter out type-only specifiers\n      // e.g., `export { value, type TypeOnly }` -> `export { value }`\n      if (node.specifiers.length > 0) {\n        node.specifiers = node.specifiers.filter((specifier) => {\n          if (t.isExportSpecifier(specifier)) {\n            return specifier.exportKind !== 'type'\n          }\n          return true\n        })\n\n        // If all specifiers were removed, remove the entire export declaration\n        // (unless it has a declaration like `export const x = 1`)\n        if (node.specifiers.length === 0 && !node.declaration) {\n          return false\n        }\n      }\n    }\n\n    // Handle type-only export-all declarations\n    // e.g., `export type * from './module'`\n    if (t.isExportAllDeclaration(node)) {\n      if (node.exportKind === 'type') {\n        return false\n      }\n    }\n\n    // Handle import declarations\n    if (t.isImportDeclaration(node)) {\n      // Remove entire import if it's a type-only import\n      // e.g., `import type { Foo } from './module'`\n      if (node.importKind === 'type') {\n        return false\n      }\n\n      // For value imports with mixed specifiers, filter out type-only specifiers\n      // e.g., `import { value, type TypeOnly } from './module'` -> `import { value }`\n      if (node.specifiers.length > 0) {\n        node.specifiers = node.specifiers.filter((specifier) => {\n          if (t.isImportSpecifier(specifier)) {\n            return specifier.importKind !== 'type'\n          }\n          return true\n        })\n\n        // If all specifiers were removed, remove the entire import declaration\n        if (node.specifiers.length === 0) {\n          return false\n        }\n      }\n    }\n\n    return true\n  })\n}\n\n// Re-export findReferencedIdentifiers from babel-dead-code-elimination\nexport { findReferencedIdentifiers }\n\n/**\n * Performs dead code elimination on the AST, with TypeScript type stripping.\n *\n * This is a wrapper around babel-dead-code-elimination that first strips\n * TypeScript type-only exports and imports. This is necessary because\n * babel-dead-code-elimination doesn't handle type exports, which can cause\n * imports to be retained when they're only referenced by type exports.\n *\n * @param ast - The Babel AST to mutate\n * @param candidates - Optional set of identifier paths to consider for removal.\n *                     If provided, only these identifiers will be candidates for removal.\n *                     This should be the result of `findReferencedIdentifiers(ast)` called\n *                     before any AST transformations.\n */\nexport function deadCodeElimination(\n  ast: ParseResult<_babel_types.File>,\n  candidates?: ReturnType<typeof findReferencedIdentifiers>,\n): void {\n  // First strip TypeScript type-only exports and imports\n  stripTypeExports(ast)\n\n  // Then run the original dead code elimination\n  _deadCodeElimination(ast, candidates)\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,SAAS,EAAE,MAAM,GAAG,QAAyC;AAC3E,SAAA,GAAA,cAAA,OAAa,MAAM;EACjB,SAAS;GACP;GACA;GACA;GACA;GACA;GACA,CAAC,cAAc,EAAE,wBAAwB,MAAM,CAAC;GAChD;GACD;EACD,YAAY;EACZ,GAAG;EACJ,CAAC;;AAGJ,IAAI,WAAW,iBAAA;AAEf,IAAI,aAAa,SACf,YAAW,SAAS;AAItB,SAAgB,gBACd,KACA,MACiB;AACjB,QAAO,SACL,KACA,OACI;EAAE,yBAAyB;EAAQ,YAAY;EAAM,GAAG;EAAM,GAC9D,KAAA,EACL;;;;;;;;;;;;;;;;;;;;;;;;AA0BH,SAAgB,iBAAiB,KAA2C;AAE1E,KAAI,QAAQ,OAAO,IAAI,QAAQ,KAAK,QAAQ,SAAS;AAEnD,MAAI,aAAE,yBAAyB,KAAK,EAAE;AAGpC,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,aAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAIF,QAAI,KAAK,WAAW,WAAW,KAAK,CAAC,KAAK,YACxC,QAAO;;;AAOb,MAAI,aAAE,uBAAuB,KAAK;OAC5B,KAAK,eAAe,OACtB,QAAO;;AAKX,MAAI,aAAE,oBAAoB,KAAK,EAAE;AAG/B,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,aAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAGF,QAAI,KAAK,WAAW,WAAW,EAC7B,QAAO;;;AAKb,SAAO;GACP;;;;;;;;;;;;;;;;AAoBJ,SAAgB,oBACd,KACA,YACM;AAEN,kBAAiB,IAAI;AAGrB,EAAA,GAAA,4BAAA,qBAAqB,KAAK,WAAW"}