|
1 | 1 | import { globSync } from 'glob' |
2 | 2 | import path from 'path' |
| 3 | +import fs from 'fs' |
3 | 4 | import debugModule from 'debug' |
4 | 5 | const debug = debugModule('codeceptjs:container') |
5 | 6 | import { MetaStep } from './step.js' |
@@ -674,12 +675,65 @@ async function loadSupportObject(modulePath, supportObjectName) { |
674 | 675 | try { |
675 | 676 | // Use dynamic import for both ESM and CJS modules |
676 | 677 | let importPath = modulePath |
677 | | - // Append .js if no extension provided (ESM resolution requires it) |
| 678 | + let tempJsFile = null |
| 679 | + |
678 | 680 | if (typeof importPath === 'string') { |
679 | 681 | const ext = path.extname(importPath) |
680 | | - if (!ext) importPath = `${importPath}.js` |
| 682 | + |
| 683 | + // Handle TypeScript files |
| 684 | + if (ext === '.ts') { |
| 685 | + try { |
| 686 | + const { transpile } = await import('typescript') |
| 687 | + const tsContent = fs.readFileSync(importPath, 'utf8') |
| 688 | + |
| 689 | + // Transpile TypeScript to JavaScript with ES module output |
| 690 | + const jsContent = transpile(tsContent, { |
| 691 | + module: 99, // ModuleKind.ESNext |
| 692 | + target: 99, // ScriptTarget.ESNext |
| 693 | + esModuleInterop: true, |
| 694 | + allowSyntheticDefaultImports: true, |
| 695 | + }) |
| 696 | + |
| 697 | + // Create a temporary JS file with .mjs extension to force ES module treatment |
| 698 | + tempJsFile = importPath.replace('.ts', '.temp.mjs') |
| 699 | + fs.writeFileSync(tempJsFile, jsContent) |
| 700 | + importPath = tempJsFile |
| 701 | + } catch (tsError) { |
| 702 | + throw new Error(`Failed to compile TypeScript file ${importPath}: ${tsError.message}`) |
| 703 | + } |
| 704 | + } else if (!ext) { |
| 705 | + // Append .js if no extension provided (ESM resolution requires it) |
| 706 | + importPath = `${importPath}.js` |
| 707 | + } |
| 708 | + } |
| 709 | + |
| 710 | + let obj |
| 711 | + try { |
| 712 | + obj = await import(importPath) |
| 713 | + } catch (importError) { |
| 714 | + // Clean up temp file if created before rethrowing |
| 715 | + if (tempJsFile) { |
| 716 | + try { |
| 717 | + if (fs.existsSync(tempJsFile)) { |
| 718 | + fs.unlinkSync(tempJsFile) |
| 719 | + } |
| 720 | + } catch (cleanupError) { |
| 721 | + // Ignore cleanup errors |
| 722 | + } |
| 723 | + } |
| 724 | + throw importError |
| 725 | + } finally { |
| 726 | + // Clean up temp file if created |
| 727 | + if (tempJsFile) { |
| 728 | + try { |
| 729 | + if (fs.existsSync(tempJsFile)) { |
| 730 | + fs.unlinkSync(tempJsFile) |
| 731 | + } |
| 732 | + } catch (cleanupError) { |
| 733 | + // Ignore cleanup errors |
| 734 | + } |
| 735 | + } |
681 | 736 | } |
682 | | - const obj = await import(importPath) |
683 | 737 |
|
684 | 738 | // Handle ESM module wrapper |
685 | 739 | let actualObj = obj |
|
0 commit comments