[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.yml]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".github/DISCUSSION_TEMPLATE/q-a.yml",
    "content": "body:\n  - type: markdown\n    attributes:\n      value: |\n        ## 💬 What's your question?\n\n        <details>\n          <summary><em>Need some pointers on crafting your question?</em></summary>\n\n          <br>\n\n          1. **Start succinctly:** Jump to the point with a concise question.\n          2. **Conciseness matters:** Keep it brief yet specific; avoid lengthy explanations.\n          3. **Include code:** Attach relevant code snippets, configurations, and errors.\n          4. **Add screenshots:** If applicable, provide screenshots.\n        </details>\n\n  - type: textarea\n    id: improvements\n    attributes:\n      label: Question\n    validations:\n      required: true\n\n  - type: markdown\n    attributes:\n      value: |\n        <br>\n\n        > **🚀 Try _Priority Support_!**\n        >\n        > If you're in a pinch, don't hesitate to take advantage of my [_Priority Support_ service](https://github.com/sponsors/privatenumber) where you can ask me questions in an exclusive forum. I'm well equppied to assist you with this project and would be happy to help you out! 🙂\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "content": "name: 🐛 Bug report\ndescription: Found a bug? File a report and let's get it fixed!\nlabels: [bug, pending triage]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        💁‍♂️ This is a collaborative effort. Please do your best to debug, communicate, and demonstrate the problem.\n\n  - type: checkboxes\n    attributes:\n      label: Acknowledgements\n      options:\n        - label: I read the documentation and searched existing issues to avoid duplicates\n          required: true\n\n        - label: I understand this is a **bug tracker** and anything other than a proven bug will be closed\n          required: true\n\n        - label: I understand this is a free project and relies on community contributions\n          required: true\n\n        - label: I read and understood the [Contribution guide](https://github.com/privatenumber/tsx/blob/master/CONTRIBUTING.md)\n          required: true\n\n  - type: markdown\n    attributes:\n      value: |\n        ## 📋 Show us the bug\n\n        > [!CAUTION]\n        > Without proving the bug is in tsx via *minimal* reproduction, your issue will be closed without response.\n\n        The minimal reproduction is the core of your issue. This is usually all we read.\n\n        The first thing we'll do is scrutinize every code, file, and dependency to see how they impact the bug. If you can delete it and still produce the bug, it's not needed.\n\n        **Starter Template**: [Fork this StackBlitz template](https://stackblitz.com/edit/node-huzszn?file=index.ts)\n        If it's not reproducible on StackBlitz, upload it to a GitHub repository and use GitHub Actions to show the error.\n\n        Please do your best to _show_ the bug rather than talking about it. This will lead to a speedy resolution.\n\n  - type: input\n    attributes:\n      label: Minimal reproduction URL\n      placeholder: https://github.com/...\n    validations:\n      required: true\n\n  - type: markdown\n    attributes:\n      value: |\n        > [!TIP]\n        > **🙋 Need help?** Use [_Priority Support_](https://github.com/sponsors/privatenumber) for debugging help and implementation!\n\n  - type: markdown\n    attributes:\n      value: |\n        ## 🗒️ Notes\n\n        > [!IMPORTANT]\n        > Please skip this section and focus on minimizing the reproduction. We only read it _after_ verifying the reproduction above.\n\n  - type: textarea\n    attributes:\n      label: Problem & expected behavior (under 200 words)\n      value: |\n        Skip this section and let your reproduction do the talking...\n\n\n\n\n        But if you really need to explain, keep it under 200 words:\n        - What happened\n        - What I expected\n        - Error stack trace\n        - Documentation links\n        - Screenshots\n\n  - type: markdown\n    attributes:\n      value: |\n        ## 🛠️ Contribute\n\n  - type: checkboxes\n    attributes:\n      label: Bugs are expected to be fixed by those affected by it\n      options:\n        - label: I'm interested in working on this issue\n\n  - type: checkboxes\n    attributes:\n      label: Compensating engineering work will speed up resolution and support the project\n      options:\n        - label: I'm willing to offer $10 for financial support\n\n  - type: markdown\n    attributes:\n      value: |\n        ## 🚀 Need immediate help?\n        Escalate this issue by supporting the project as a [_Priority Patron_](https://github.com/sponsors/privatenumber)!\n\n        Your concern will receive prompt attention, ensuring faster and more efficient resolution.\n\n        [→ Become a _Priority Patron_!](https://github.com/sponsors/privatenumber)\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: 💖 [Sponsors only] Feature requests / Help / Questions\n    url: https://github.com/sponsors/privatenumber/\n    about: Need help ASAP? Get prioritized help for all your questions and issues!\n\n  - name: 📚 Contribution guide\n    url: https://github.com/privatenumber/tsx/blob/develop/CONTRIBUTING.md\n    about: Learn more about contributing to this project\n"
  },
  {
    "path": ".github/renovate.json",
    "content": "{\n\t\"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n\t\"enabledManagers\": [\"nvm\"]\n}\n"
  },
  {
    "path": ".github/workflows/lock-threads.yml",
    "content": "name: Lock threads\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: \"0 0 * * 0\" # Every Sunday\n\njobs:\n  lock:\n    runs-on: ubuntu-latest\n\n    permissions:\n      issues: write\n      pull-requests: write\n      discussions: write\n\n    steps:\n      - uses: dessant/lock-threads@v5\n        with:\n          github-token: ${{ github.token }}\n          issue-inactive-days: \"91\"\n          add-issue-labels: outdated\n          pr-inactive-days: \"91\"\n          add-pr-labels: outdated\n          discussion-inactive-days: \"91\"\n          add-discussion-labels: outdated\n          log-output: \"true\"\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    branches: [master, develop]\n\npermissions:\n  contents: write\n\njobs:\n  release:\n    name: Release\n    if: (\n      github.repository_owner == 'pvtnbr' && github.ref_name =='develop'\n      ) || (\n      github.repository_owner == 'privatenumber' && github.ref_name =='master'\n      )\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          token: ${{ secrets.GH_TOKEN }}\n\n      - name: Use Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version-file: .nvmrc\n\n      - name: Setup pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          run_install: true\n\n      - name: Lint\n        run: pnpm lint\n\n      - name: Prerelease to GitHub\n        if: github.repository_owner == 'pvtnbr'\n        run: |\n          git remote add public https://github.com/$(echo $GITHUB_REPOSITORY | sed \"s/^pvtnbr/privatenumber/\")\n          git fetch public master 'refs/tags/*:refs/tags/*'\n          git push --force --tags origin refs/remotes/public/master:refs/heads/master\n\n          jq '\n              .publishConfig.registry = \"https://npm.pkg.github.com\"\n            | .name = (\"@\" + env.GITHUB_REPOSITORY_OWNER + \"/\" + .name)\n            | .repository = env.GITHUB_REPOSITORY\n            | .release.branches = [\n                \"master\",\n                { name: \"develop\", prerelease: \"rc\", channel: \"latest\" }\n              ]\n            ' package.json > _package.json\n          mv _package.json package.json\n\n      - name: Release\n        env:\n          GH_TOKEN: ${{ secrets.GH_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n        run: pnpm dlx semantic-release@24\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Test\non:\n  push:\n    branches: [master, develop]\n  pull_request:\njobs:\n  test:\n    name: Test\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest]\n    timeout-minutes: 10\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Use Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version-file: .nvmrc\n\n      - name: Authenticate GitHub registry\n        run: npm set \"//npm.pkg.github.com:_authToken=${{ secrets.GH_TOKEN }}\"\n\n      - name: Setup pnpm\n        uses: pnpm/action-setup@v4\n\n      - name: Get pnpm store directory\n        shell: bash\n        run: echo \"PNPM_STORE=$(pnpm store path --silent)\" >> $GITHUB_ENV\n\n      - name: Restore pnpm cache\n        id: pnpm-cache\n        uses: actions/cache@v3\n        with:\n          path: ${{ env.PNPM_STORE }}\n          key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}\n          restore-keys: ${{ runner.os }}-pnpm-\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Save pnpm cache\n        if: steps.pnpm-cache.outputs.cache-hit != 'true'\n        uses: actions/cache/save@v3\n        with:\n          path: ${{ env.PNPM_STORE }}\n          key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}\n\n      - name: Get Node.js cache directory\n        shell: bash\n        run: echo \"NVE_CACHE=$(node -p 'require(\"cachedir\")(\"nve\")')\" >> $GITHUB_ENV\n\n      - name: Cache Node.js versions\n        uses: actions/cache@v3\n        with:\n          path: ${{ env.NVE_CACHE }}\n          key: ${{ runner.os }}-nodejs-${{ hashFiles('.nvmrc') }}-${{ hashFiles('tests/utils/node-versions.ts') }}\n          restore-keys: ${{ runner.os }}-nodejs-\n\n      - name: Test\n        run: pnpm test\n\n      - name: Type check\n        if: ${{ matrix.os == 'ubuntu-latest' }}\n        run: pnpm type-check\n\n      - name: Lint\n        if: ${{ matrix.os == 'ubuntu-latest' }}\n        run: pnpm lint\n"
  },
  {
    "path": ".gitignore",
    "content": "# macOS\n.DS_Store\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# Dependency directories\nnode_modules\n\n# Output of 'npm pack'\n*.tgz\n\n# dotenv environment variables file\n.env\n.env.test\n\n# Cache\n.eslintcache\n\n# Distribution\ndist\n\n# Link config\nlink.config.json\n\n# Vitepress\ndocs/.vitepress/cache\n"
  },
  {
    "path": ".nvmrc",
    "content": "20.19.3\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n\t\"typescript.tsdk\": \"node_modules/typescript/lib\"\n}\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribution guide\n\nWelcome! We're excited you're interested in contributing. To ensure a smooth and productive collaboration, follow these guidelines.\n\n## Goals of tsx\n\n1. Enhance Node.js with TypeScript support\n2. Improve ESM ↔ CommonJS interoperability as the ecosystem migrates to ESM\n3. Support the [active LTS versions of Node.js](https://endoflife.date/nodejs)\n\n## Issues & Discussions\n\n> [!IMPORTANT]\n> Please be polite, respectful, and considerate of people's time and effort.\n>\n> This is an open source project relying on community contributions.\n\n### Opening a new Issue\n\n> [!IMPORTANT]\n> The Issues tab is a bug & feature tracker. Not a place for debugging support. To keep threads concise and easy to follow for collaborators, please participate constructively and follow the guidelines.\n\n#### Minimal reproduction required\n\nProvide a clear, minimal example of the issue. This helps contributors identify genuine bugs efficiently.\n\n#### Check the documentation\n\nReview the project documentation for known behaviors or caveats to avoid unnecessary issues.\n\n### Commenting on an existing Issue\n\n#### ⭐️ Issue objectives\n\nIssues serve as a platform for **contributors** to:\n1. Verify bugs\n2. Diagnose the causes\n3. Brainstorm solutions\n4. Implement fix\n\n#### ✅ Be constructive\n\nAim to contribute to the solution with research & PRs (tests + solutions). The goal is to land an improvement in _tsx_ for everyone to benefit.\n\nBe concise to save people's time.\n\n#### ❌ Avoid detractive comments\n\nKeep comments constructive towards fixing the issue.\n\nThese types of comments will be hidden or deleted:\n- Comments that pollute the thread (e.g. \"updates?\", \"me too\", \"also happening in ...\")\n- Discussing workarounds that can't land in _tsx_\n- Off-topic comments\n\nAfter an issue is confirmed by the provided reproduction, the thread may sometimes be locked to direct further conversation & action to PRs.\n\n> [!TIP]\n> **⚡️ Get issues addressed faster!**\n>\n> Sponsors can prioritize issues. By helping fund development, you can ensure your needs are addressed quickly!\n>\n> [Sponsor now →](https://github.com/sponsors/privatenumber)\n\n## Pull requests\n\n#### Open an Issue first\n\nEnsure there’s an existing issue related to your PR to facilitate alignment and prevent wasted work.\n\n#### Include tests\n\nAdd minimal tests verifying your changes to maintain behavior and reliability.\n\n## Development\n\n### Initial setup\n\nAfter cloning the repo, use [nvm](https://nvm.sh) (optional) to set the expected Node.js version, and [pnpm](https://pnpm.io) to install dependencies:\n\n```bash\nnvm i      # Install or use Node.js version\npnpm i     # Install dependencies\n```\n\n### Building\n\nBuild the source code with:\n\n```bash\npnpm build # Compiles to `dist`\n```\n\n> [!TIP]\n> Temporarily disable minification by removing `--minify` in `package.json#scripts.build` for easier debugging.\n\n\n### Linting and type-checking\n\nEnsure code quality with:\n\n```bash\npnpm lint           # ESLint\npnpm type-check     # TypeScript type checking\n```\n\n### Testing\n\nRun automated tests with:\n\n```bash\npnpm test             # Regular test\nCI=1 pnpm test        # CI environments\n```\n\n### Manual testing\n\n#### Local testing\n\nUse the absolute path to run `./dist/cli.mjs`:\n\n```sh\n/tsx/dist/cli.mjs <ts file>\n```\n\n#### Collaborative testing\n\nUse [`git-publish`](https://github.com/privatenumber/git-publish) to publish your changes to your GitHub fork. It can be shared with others and installed from for testing.\n\n\n## Giving back\n\n<img align=\"center\" src=\"https://badgen.net/npm/dm/tsx\">\n\n_tsx_ has outgrown its \"hobby project\" status to become a tool used and loved by many.\n\nWhile it made it far without sponsorship, funding will accelerate further development by making it easier for devs to choose tsx over other paid work.\n\nIf tsx has helped you, help tsx back! ❤️\n\nAny amount makes a difference.\n\n[Sponsor now →](https://github.com/sponsors/privatenumber)\n"
  },
  {
    "path": "FUNDING.json",
    "content": "{\n\t\"drips\": {\n\t\t\"ethereum\": {\n\t\t\t\"ownedBy\": \"0xB9C2F7C3BB7734c37d2949B98A90bAea2fd59E21\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Hiroki Osame <hiroki.osame@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "<h1 align=\"center\">\n<br>\n<picture>\n\t<source media=\"(prefers-color-scheme: dark)\" srcset=\".github/logo-dark.svg\">\n\t<img width=\"160\" alt=\"tsx\" src=\".github/logo-light.svg\">\n</picture>\n<br><br>\n<a href=\"https://npm.im/tsx\"><img src=\"https://badgen.net/npm/v/tsx\"></a> <a href=\"https://npm.im/tsx\"><img src=\"https://badgen.net/npm/dm/tsx\"></a>\n</h1>\n\n<p align=\"center\">\nTypeScript Execute (tsx): The easiest way to run TypeScript in Node.js\n<br><br>\n<a href=\"https://tsx.is\">Documentation</a>&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"https://tsx.is/getting-started\">Getting started →</a>\n</p>\n\n<br>\n\n<p align=\"center\">\n\t<a href=\"https://github.com/sponsors/privatenumber/sponsorships?tier_id=398771\"><img width=\"412\" src=\"https://raw.githubusercontent.com/privatenumber/sponsors/master/banners/assets/donate.webp\"></a>\n\t<a href=\"https://github.com/sponsors/privatenumber/sponsorships?tier_id=416984\"><img width=\"412\" src=\"https://raw.githubusercontent.com/privatenumber/sponsors/master/banners/assets/sponsor.webp\"></a>\n</p>\n<p align=\"center\"><sup><i>Already a sponsor?</i> Join the discussion in the <a href=\"https://github.com/pvtnbr/tsx\">Development repo</a>!</sup></p>\n\n## Sponsors\n\n<p align=\"center\">\n\t<a href=\"https://github.com/sponsors/privatenumber\">\n\t\t<img src=\"https://cdn.jsdelivr.net/gh/privatenumber/sponsors/sponsorkit/sponsors.svg\">\n\t</a>\n</p>\n\n"
  },
  {
    "path": "docs/.vitepress/config.ts",
    "content": "import { defineConfig } from 'vitepress';\n\nconst title = 'tsx';\nconst description = 'tsx (TypeScript Execute) - The easiest way to run TypeScript in Node.js';\n\nexport default defineConfig({\n\tlang: 'en-US',\n\n\ttitle,\n\n\tdescription,\n\n\tlastUpdated: true,\n\n\tcleanUrls: true,\n\n\tignoreDeadLinks: true,\n\n\tmetaChunk: true,\n\n\thead: [\n\t\t['link', {\n\t\t\trel: 'icon',\n\t\t\ttype: 'image/svg+xml',\n\t\t\thref: '/logo-mini.svg',\n\t\t}],\n\t\t['meta', {\n\t\t\tproperty: 'og:title',\n\t\t\tcontent: title,\n\t\t}],\n\t\t['meta', {\n\t\t\tproperty: 'og:type',\n\t\t\tcontent: 'website',\n\t\t}],\n\t\t['meta', {\n\t\t\tproperty: 'og:image',\n\t\t\tcontent: 'https://tsx.is/social.png',\n\t\t}],\n\t\t['meta', {\n\t\t\tproperty: 'og:url',\n\t\t\tcontent: 'https://tsx.is',\n\t\t}],\n\t\t['meta', {\n\t\t\tproperty: 'og:description',\n\t\t\tcontent: description,\n\t\t}],\n\t\t['meta', {\n\t\t\tproperty: 'og:site_name',\n\t\t\tcontent: title,\n\t\t}],\n\t\t['meta', {\n\t\t\tname: 'twitter:card',\n\t\t\tcontent: 'summary_large_image',\n\t\t}],\n\t\t['meta', {\n\t\t\tname: 'twitter:site',\n\t\t\tcontent: '@tsx_is',\n\t\t}],\n\t\t['script', {\n\t\t\tsrc: 'https://beamanalytics.b-cdn.net/beam.min.js',\n\t\t\t'data-token': 'ee893e1d-7484-4fb3-85b7-78c58b3d9c9e',\n\t\t\tasync: '',\n\t\t}],\n\t],\n\n\tthemeConfig: {\n\t\tsiteTitle: false,\n\n\t\tlogo: {\n\t\t\tlight: '/logo-light.svg',\n\t\t\tdark: '/logo-dark.svg',\n\t\t\talt: 'tsx',\n\t\t},\n\n\t\toutline: 'deep',\n\n\t\teditLink: {\n\t\t\tpattern: 'https://github.com/privatenumber/tsx/edit/master/docs/:path',\n\t\t\ttext: 'Propose changes to this page',\n\t\t},\n\n\t\tnav: [\n\t\t\t{\n\t\t\t\ttext: 'User guide',\n\t\t\t\tlink: '/',\n\t\t\t\tactiveMatch: '^(?!\\/dev-api\\/).*',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttext: 'Developer API',\n\t\t\t\tlink: '/dev-api/',\n\t\t\t\tactiveMatch: '/dev-api/',\n\t\t\t},\n\t\t],\n\n\t\tsidebar: {\n\t\t\t'/': [\n\t\t\t\t{\n\t\t\t\t\ttext: 'Introduction',\n\t\t\t\t\titems: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'About tsx',\n\t\t\t\t\t\t\tlink: '/',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Getting started',\n\t\t\t\t\t\t\tlink: '/getting-started',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttext: 'Usage',\n\t\t\t\t\titems: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Node.js enhancement',\n\t\t\t\t\t\t\tlink: '/node-enhancement',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Watch mode',\n\t\t\t\t\t\t\tlink: '/watch-mode',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttext: 'Integration',\n\t\t\t\t\titems: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'TypeScript',\n\t\t\t\t\t\t\tlink: '/typescript',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Compilation',\n\t\t\t\t\t\t\tlink: '/compilation',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Shell scripts',\n\t\t\t\t\t\t\tlink: '/shell-scripts',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'VSCode debugging',\n\t\t\t\t\t\t\tlink: '/vscode',\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttext: 'Support',\n\t\t\t\t\titems: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'FAQ',\n\t\t\t\t\t\t\tlink: '/faq',\n\t\t\t\t\t\t\tdocFooterText: 'Frequently Asked Questions',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Learning resources',\n\t\t\t\t\t\t\tlink: '/learn',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Help center (Sponsors only)',\n\t\t\t\t\t\t\tlink: 'https://github.com/pvtnbr/tsx/discussions',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Become a Sponsor',\n\t\t\t\t\t\t\tlink: 'https://github.com/sponsors/privatenumber/sponsorships?tier_id=416984',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t],\n\t\t\t'/dev-api/': [\n\t\t\t\t{\n\t\t\t\t\ttext: 'About the Developer API',\n\t\t\t\t\tlink: '/dev-api/',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttext: 'Automatic registration',\n\t\t\t\t\titems: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Node.js CLI',\n\t\t\t\t\t\t\tlink: '/dev-api/node-cli'\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'Entry-point',\n\t\t\t\t\t\t\tlink: '/dev-api/entry-point'\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttext: 'Scoped TS loading',\n\t\t\t\t\titems: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'tsImport()',\n\t\t\t\t\t\t\tlink: '/dev-api/ts-import'\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'tsx.require()',\n\t\t\t\t\t\t\tlink: '/dev-api/tsx-require'\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttext: 'Register API',\n\t\t\t\t\titems: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'CommonJS',\n\t\t\t\t\t\t\tlink: '/dev-api/register-cjs'\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: 'ESM',\n\t\t\t\t\t\t\tlink: '/dev-api/register-esm'\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\n\t\tsocialLinks: [\n\t\t\t{\n\t\t\t\ticon: 'github',\n\t\t\t\tlink: 'https://github.com/privatenumber/tsx',\n\t\t\t},\n\t\t\t{\n\t\t\t\ticon: 'x',\n\t\t\t\tlink: 'https://x.com/tsx_is',\n\t\t\t},\n\t\t\t{\n\t\t\t\ticon: {\n\t\t\t\t\tsvg: '<svg viewBox=\"0 0 24 24\"><path d=\"M22 4H2v16h20zm-2 4l-8 5l-8-5V6l8 5l8-5z\"/></svg>'\n\t\t\t\t},\n\t\t\t\tlink: '/contact'\n\t\t\t}\n\t\t],\n\n\t\tsearch: {\n\t\t\tprovider: 'local',\n\t\t},\n\n\t\tcarbonAds: {\n\t\t\tcode: 'CW7DEKJY',\n\t\t\tplacement: 'tsxis',\n\t\t},\n\t},\n});\n"
  },
  {
    "path": "docs/.vitepress/theme/components/AsideSponsors.vue",
    "content": "<template>\n\t<div class=\"mb-8\">\n\t\t<div>\n\t\t\t<h4 class=\"text-base font-semibold\">Premium sponsors</h4>\n\t\t</div>\n\t\t<a\n\t\t\thref=\"https://sevalla.com\"\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener\"\n\t\t>\n\t\t\t<div class=\"my-4 py-6 px-6 bg-white/5\">\n\t\t\t\t<img\n\t\t\t\t\tsrc=\"/logos/sevalla-full.svg\"\n\t\t\t\t\talt=\"Sevalla\"\n\t\t\t\t\tclass=\"object-cover\"\n\t\t\t\t>\n\t\t\t</div>\n\t\t</a>\n\t\t<a\n\t\t\thref=\"https://github.com/sponsors/privatenumber/sponsorships?pay_prorated=false&tier_id=388346\"\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener\"\n\t\t\tclass=\"sponsor-button\"\n\t\t>\n\t\t\tBecome a premium sponsor\n\t\t</a>\n\t</div>\n</template>\n\n<style scoped>\n.sponsor-button {\n\t@apply\n\t\tblock\n\t\tw-fit\n\t\tmx-auto\n\t\ttext-xs\n\t\trounded-full\n\t\ttransition-colors\n\t\tbg-pink-500\n\t\thover:bg-pink-600\n\t\ttext-white\n\t\tmt-5\n\t\tpy-1.5\n\t\tpx-4;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/ContactForm.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue';\n\nconst isSending = ref(false);\nconst name = ref('');\nconst email = ref('');\nconst subject = ref('');\nconst message = ref('');\n\nconst sendMessage = async () => {\n\tisSending.value = true;\n\n\tconst body = new FormData();\n\tbody.append('name', name.value);\n\tbody.append('email', email.value);\n\tbody.append('subject', subject.value);\n\tbody.append('message', message.value);\n\tbody.append('access_key', '122038f1-9646-4bb3-89de-55ab3e1bed50');\n\n\tconst fetching = await fetch(\n\t\t'https://api.web3forms.com/submit',\n\t\t{\n\t\t\tmethod: 'POST',\n\t\t\tbody,\n\t\t},\n\t);\n\n\tconst response = await fetching.json();\n\n\tif (response.success) {\n\t\t// show popup\n\t}\n\n\tname.value = '';\n\temail.value = '';\n\tsubject.value = '';\n\tmessage.value = '';\n\tisSending.value = false;\n};\n</script>\n\n<template>\n\t<div class=\"mx-auto\">\n\t\t<form @submit.prevent=\"sendMessage\">\n\t\t\t<div\n\t\t\t\tclass=\"\n\t\t\t\tflex\n\t\t\t\tflex-wrap\n\t\t\t\tmd:flex-nowrap\n\t\t\t\tgap-4\n\t\t\t\tmy-4\n\t\t\t\"\n\t\t\t>\n\t\t\t\t<label class=\"w-full\">\n\t\t\t\t\t<div class=\"label\">Name</div>\n\t\t\t\t\t<input\n\t\t\t\t\t\tv-model=\"name\"\n\t\t\t\t\t\tclass=\"w-full\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t\t:disabled=\"isSending\"\n\t\t\t\t\t\tplaceholder=\"Your name\"\n\t\t\t\t\t>\n\t\t\t\t</label>\n\n\t\t\t\t<label class=\"w-full\">\n\t\t\t\t\t<div class=\"label\">Email</div>\n\t\t\t\t\t<input\n\t\t\t\t\t\tv-model=\"email\"\n\t\t\t\t\t\tclass=\"w-full\"\n\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\tname=\"email\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t\t:disabled=\"isSending\"\n\t\t\t\t\t\tplaceholder=\"your@email.com\"\n\t\t\t\t\t>\n\t\t\t\t</label>\n\t\t\t</div>\n\t\t\t<div\n\t\t\t\tclass=\"\n\t\t\t\tflex\n\t\t\t\tflex-wrap\n\t\t\t\tmd:flex-nowrap\n\t\t\t\tgap-4\n\t\t\t\tmy-4\n\t\t\t\"\n\t\t\t>\n\t\t\t\t<label class=\"w-full\">\n\t\t\t\t\t<div class=\"label\">Subject</div>\n\t\t\t\t\t<input\n\t\t\t\t\t\tv-model=\"subject\"\n\t\t\t\t\t\tclass=\"w-full\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tname=\"subject\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t\t:disabled=\"isSending\"\n\t\t\t\t\t\tplaceholder=\"Sponsorship, consultation, etc.\"\n\t\t\t\t\t>\n\t\t\t\t</label>\n\t\t\t</div>\n\n\t\t\t<label class=\"block my-5\">\n\t\t\t\t<div class=\"label\">Message</div>\n\t\t\t\t<textarea\n\t\t\t\t\tv-model=\"message\"\n\t\t\t\t\tclass=\"w-full h-40\"\n\t\t\t\t\tplaceholder=\"Hey there, can I ask you a question?\"\n\t\t\t\t\t:disabled=\"isSending\"\n\t\t\t\t\trequired\n\t\t\t\t/>\n\t\t\t</label>\n\n\t\t\t<div class=\"flex flex-row-reverse\">\n\t\t\t\t<button\n\t\t\t\t\ttitle=\"Send email\"\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tclass=\"send-email button\"\n\t\t\t\t\t:disabled=\"isSending\"\n\t\t\t\t>\n\t\t\t\t\t<template v-if=\"isSending\">\n\t\t\t\t\t\tSending...\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-else>\n\t\t\t\t\t\tSend\n\t\t\t\t\t</template>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</form>\n\t</div>\n</template>\n\n<style scoped>\ninput, textarea, select {\n\t@apply\n\t\trounded\n\t\tbg-zinc-100\n\t\tdark:bg-zinc-950\n\t\tpy-2\n\t\tpx-4;\n}\n\nlabel {\n\t@apply\n\t\tflex\n\t\tflex-col\n\t\tgap-2;\n}\n\n.send-email {\n\t@apply\n\t\tbg-blue-500\n\t\ttext-white;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/ImageLink.vue",
    "content": "<script setup lang=\"ts\">\ndefineProps<{\n\timgSrc: string;\n\thref: string;\n\talt: string;\n}>();\n</script>\n\n<template>\n\t<a\n\t\tclass=\"link\"\n\t\t:href=\"href\"\n\t\t:title=\"alt\"\n\t>\n\t\t<img\n\t\t\t:src=\"imgSrc\"\n\t\t\t:alt=\"alt\"\n\t\t>\n\t</a>\n</template>\n\n<style scoped>\n.link {\n\t@apply\n\t\tp-2\n\t\tbox-border;\n}\n\nimg {\n\t@apply\n\t\th-full\n\t\tdrop-shadow;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/Marquee.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\n\nconst reflow = (element: HTMLElement) => {\n\telement.style.display = 'none';\n\telement.offsetHeight;\n\telement.style.display = '';\n};\n\nconst waitImageLoad = (\n\timg: HTMLImageElement,\n) => new Promise<void>(\n\t(resolve) => {\n\t\tif (img.complete) {\n\t\t\treturn resolve();\n\t\t}\n\n\t\timg.addEventListener('load', () => resolve());\n\t\timg.addEventListener('error', () => resolve());\n\t}\n);\n\nconst waitImages = (\n\telement: HTMLElement,\n) => {\n\tconst images = element.querySelectorAll('img');\n\treturn Promise.all(\n\t\tArray.from(images).map(async (image) => {\n\t\t\tawait waitImageLoad(image);\n\t\t\t/**\n\t\t\t * Bug in Safari where preloaded image causes the image to have\n\t\t\t * 0 width.\n\t\t\t * Load the FAQ page then navigating to the index page.\n\t\t\t * Solution is to trigger reflow.\n\t\t\t */\n\t\t\tif (image.offsetWidth === 0) {\n\t\t\t\treflow(image);\n\t\t\t}\n\t\t})\n\t);\n};\n\nconst props = defineProps<{\n\tvelocity: number;\n}>();\n\nconst $content = ref(null);\n\n/**\n * Animation shouldn't start until the content is loaded and the width is\n * determined. Otherwise it will move at the rate of the initial width\n */\nconst animationDuration = ref({\n\tanimationDuration: '',\n});\nconst computeAnimationDuration = () => {\n\tanimationDuration.value.animationDuration = `${$content.value.offsetWidth / props.velocity}s`;\n};\n\nconst isPageVisible = ref<boolean>();\nconst checkIsPageVisible = () => {\n\tisPageVisible.value = document.visibilityState === 'visible';\n};\n\nonMounted(() => {\n\tdocument.addEventListener('visibilitychange', checkIsPageVisible);\n\tcheckIsPageVisible();\n\n\tif ($content.value) {\n\t\twaitImages($content.value).then(computeAnimationDuration);\n\t}\n});\n</script>\n\n<template>\n\t<div\n\t\t:class=\"[\n\t\t\t'marquee',\n\t\t\t{ moving: isPageVisible },\n\t\t]\"\n\t>\n\t\t<div\n\t\t\tclass=\"content\"\n\t\t\tref=\"$content\"\n\t\t\t:style=\"animationDuration\"\n\t\t>\n\t\t\t<slot />\n\t\t</div>\n\t\t<div\n\t\t\tclass=\"content\"\n\t\t\t:style=\"animationDuration\"\n\t\t>\n\t\t\t<slot />\n\t\t</div>\n\t</div>\n</template>\n\n<style scoped>\n.marquee {\n\tdisplay: flex;\n\twhite-space: nowrap;\n\toverflow: hidden;\n}\n\n.content {\n\tmin-width: max-content;\n}\n\n.moving .content {\n\tanimation: move-left linear infinite;\n}\n\n\n@keyframes move-left {\n\t0% {\n\t\ttransform: translateX(0%);\n\t}\n\t100% {\n\t\ttransform: translateX(-100%);\n\t}\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/Sponsors.vue",
    "content": "<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue';\n\nconst svgUrl = 'https://cdn.jsdelivr.net/gh/privatenumber/sponsors/sponsorkit/sponsors.svg';\nconst svgContent = ref<string>('');\n\nconst fetchSvg = async () => {\n    const response = await fetch(svgUrl);\n    const svgText = await response.text();\n    svgContent.value = svgText.replace('<svg ', '<svg style=\"width:100%;height:auto;\" ');\n};\n\nonMounted(() => {\n    fetchSvg();\n});\n</script>\n\n<template>\n    <div\n        v-if=\"svgContent\"\n        v-html=\"svgContent\"\n    />\n    <a\n        v-else\n        href=\"https://github.com/sponsors/privatenumber/sponsorships?tier_id=416984\"\n        target=\"_blank\"\n    >\n\t\t<img :src=\"svgUrl\">\n\t</a>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/index.ts",
    "content": "import { h } from 'vue';\nimport DefaultTheme from 'vitepress/theme';\nimport AsideSponsors from './components/AsideSponsors.vue';\nimport './styles.css';\n\nexport default {\n\textends: DefaultTheme,\n\tLayout: () => h(\n\t\tDefaultTheme.Layout,\n\t\tnull,\n\t\t{\n\t\t\t'aside-ads-before': () => h(AsideSponsors),\n\t\t},\n\t),\n};\n"
  },
  {
    "path": "docs/.vitepress/theme/styles.css",
    "content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n.button {\n\t@apply\n\t\tinline-block\n\t\tpy-2\n\t\tpx-6\n\t\trounded-full\n\t\t!no-underline\n\t\t!transition-colors\n\t\tduration-200\n\t\t;\n}\n\n.dark .dark-zebra-pattern {\n\tbackground-image: repeating-linear-gradient(\n\t\t45deg,\n\t\ttransparent,\n\t\ttransparent 10px,\n\t\trgb(0 0 0/ 0.05) 10px,\n\t\trgb(0 0 0/ 0.05) 20px\n\t);\n}\n"
  },
  {
    "path": "docs/compilation.md",
    "content": "# Compilation\n\nCompiling your TypeScript files to JavaScript is not handled by _tsx_, but it's a necessary step in most setups.\n\n::: info Should I publish TypeScript files?\n\nNo. While _tsx_ is capable of running TypeScript files in dependencies if need be (e.g. monorepos), it's highly discouraged to publish uncompiled TypeScript. Source files require a specific compilation configuration in `tsconfig.json` which may not be read, and [TypeScript performance will degrade](https://x.com/atcb/status/1705675335814271157).\n:::\n\n## Compiling an npm package\n\nnpm packages are distinguished from applications by defining package entry-points in `package.json`.\n\n[pkgroll](https://github.com/privatenumber/pkgroll) is the recommended bundler for projects using _tsx_. It's developed by the same author and used to compile _tsx_.\n\nGiven your source files are in the `src` directory, it automatically infers how to build your package based on the entry points defined in `package.json` by outputting them to the `dist` directory.\n\n### Setup\n\n::: details Basic setup\n\nSet your entry-point in [`exports`](https://nodejs.org/api/packages.html#exports):\n\n```json5\n// package.json\n{\n    \"exports\": \"./dist/index.mjs\"\n}\n```\n:::\n\n::: details Dual package (CJS & ESM)\n\nSet your CommonJS & Module entry-points in [`exports`](https://nodejs.org/api/packages.html#exports):\n\n```json5\n// package.json\n{\n    \"main\": \"./dist/index.cjs\",\n    \"module\": \"./dist/index.mjs\",\n    \"types\": \"./dist/index.d.cts\",\n\n    \"exports\": {\n        \"require\": {\n            \"types\": \"./dist/index.d.cts\",\n            \"default\": \"./dist/index.cjs\"\n        },\n        \"import\": {\n            \"types\": \"./dist/index.d.mts\",\n            \"default\": \"./dist/index.mjs\"\n        }\n    }\n}\n```\n:::\n\n::: details Command-line package\n\nSet your CLI entry-point in [`bin`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#bin):\n\n```json5\n// package.json\n{\n    \"bin\": \"./dist/cli.mjs\"\n}\n```\n:::\n\n### Build\nIn your directory, simply run `pkgroll`:\n\n::: code-group\n```sh [npm]\n$ npx pkgroll\n```\n\n```sh [pnpm]\n$ pnpm pkgroll\n```\n\n```sh [yarn]\n$ yarn pkgroll\n```\n:::\n\nOptionally, add a `build` script for convenience:\n```json\n// package.json\n{\n    // Optional: build script\n    \"scripts\": {// [!code ++]\n        \"build\": \"pkgroll\"// [!code ++]\n    }// [!code ++]\n}\n```\n\n<!-- ## Compiling an application -->\n"
  },
  {
    "path": "docs/contact.md",
    "content": "# Contact\n\n<script setup lang=\"ts\">\nimport ContactForm from './.vitepress/theme/components/ContactForm.vue';\n</script>\n\n<ContactForm />\n"
  },
  {
    "path": "docs/dev-api/entry-point.md",
    "content": "# Entry-point\n\nImport `tsx` at the top of your entry-file:\n```js\nimport 'tsx'\n\n// Now you can load TS files\nawait import('./file.ts')\n```\n<!-- TODO: does this work in CJS mode? -->\n\nNote, because of the order of static import evaluation in ESM, the enhancement only works on [dynamic imports after registration](https://nodejs.org/docs/latest-v22.x/api/module.html#:~:text=dynamic%20import()%20must%20be%20used%20for%20any%20code%20that%20should%20be%20run%20after%20the%20hooks%20are%20registered).\n\n::: danger\nEnhancing Node.js by loading _tsx_ from within your source code at run-time can be unexpected for collaborators who aren’t aware of it.\n\nWhen possible, it's recommended to use a more visible method, such as passing it as a [CLI flag](/dev-api/node-cli).\n:::\n\n\n## Advanced usage\n\n### CommonJS mode only\n\nRequire `tsx/cjs` at the top of your entry-file:\n\n```js\nrequire('tsx/cjs')\n\n// Now you can load TS files\nrequire('./file.ts')\n```\n\n### Module mode only\n\nImport `tsx/esm` at the top of your entry-file:\n\n```js\nimport 'tsx/esm'\n\n// Now you can load TS files\nawait import('./file.ts')\n```\n"
  },
  {
    "path": "docs/dev-api/index.md",
    "content": "# Developer API\nThe Developer API allows you to enhance Node.js with _tsx_ without needing to use the `tsx` command.\n\nNote that CLI features such as [_Watch mode_](/watch-mode.md) and the [REPL](/usage#repl) will not be available.\n\n## Use-cases\n\n### Directly running `node`\n\nSometimes, you may need to run `node` directly but still want to use _tsx_. Instead of using the `tsx` command, you can pass it to Node with [`node --import tsx`](/dev-api/node-cli) or you can do [`import 'tsx'`](/dev-api/entry-point) at the top of your script. This is helpful when you need more control over the Node.js environment, are integrating with tools that specifically call `node`, or simply prefer using the `node` command.\n\n### 3rd party packages\n\nSome third-party packages need to load TypeScript files, like configuration files, without affecting the entire runtime environment. The [`tsImport()` API](/dev-api/ts-import) allows these packages to load TypeScript files natively, without causing side effects to the environment.\n\n## Understanding module types\n\nUnderstanding the Node.js module types, CommonJS (CJS) and ES Module (ESM), can be helpful when using the Developer API.\n\nESM is the modern standard, indicated by the file extensions `.mjs` for JavaScript and `.mts` for TypeScript. CommonJS, the older format, uses the file extensions `.cjs` for JavaScript and `.cts` for TypeScript. When the file extension is ambiguous, such as `.js` or `.ts`, [`package.json#type`](https://nodejs.org/api/packages.html#type) is used to determine the module type. If `type` is set to `module`, the files are treated as ES Modules. If `type` is set to `commonjs` or not set at all, the files are treated as CommonJS modules.\n\nAlthough both module types can coexist in the same environment, they have distinct scopes and behaviors. _tsx_ offers APIs to enhance both CommonJS and ES modules selectively. Being aware of these distinctions and knowing which module type you are using will allow you to make informed decisions when opting into these enhancements.\n"
  },
  {
    "path": "docs/dev-api/node-cli.md",
    "content": "# Node.js CLI\n\nTo use the `node` command directly with _tsx_, pass it as a flag:\n\n```sh\nnode --import tsx ./file.ts\n```\n\n::: details (Deprecated) Node.js v20.5.1 and below\n\nOlder Node.js versions use a deprecated API `--loader` instead of `--import`.\n\n```sh\nnode --loader tsx ./file.ts\n```\n:::\n\n## Custom `tsconfig.json` path\n\nTo specify a custom path to `tsconfig.json`, use an environment variable:\n\n```sh\nTSX_TSCONFIG_PATH=./path/to/tsconfig.custom.json node --import tsx ./file.ts\n```\n\n## Binaries\n\nIf you don't have direct access to the `node` command, use the Node.js [`NODE_OPTIONS` environment variable](https://nodejs.org/api/cli.html#node_optionsoptions) to pass in the flag:\n\n```sh\nNODE_OPTIONS='--import tsx' npx some-binary\n```\n\n## Advanced usage\n\n### CommonJS mode only\n\nTo use _tsx_ for CommonJS files only:\n\n```sh\nnode --require tsx/cjs ./file.ts\n```\n\n### Module mode only\n\nTo use _tsx_ for Module files only:\n\n```sh\nnode --import tsx/esm ./file.ts\n```\n"
  },
  {
    "path": "docs/dev-api/register-cjs.md",
    "content": "# CommonJS Register API\n\nThe CommonJS Register API allows you to manually register the enhancement at runtime. But note, this only affects CommonJS modules (`.cjs`/`.cts`, and `.js`/`.ts` when `package.json#type` is unset or `commonjs`).\n\n::: warning Caveats\n\n- `import()` calls in the loaded files are not enhanced because they're handled by Node's ESM hook. Use with the [`ESM Register API`](/dev-api/register-esm).\n- Because it compiles ESM syntax to run in CommonJS mode, top-level await is not supported\n:::\n\n## Usage\n```js\nconst tsx = require('tsx/cjs/api')\n\n// Register tsx enhancement\nconst unregister = tsx.register()\n\nconst loaded = require('./file.ts')\n\n// Unregister when needed\nunregister()\n```\n\n### Scoped registration\n\nIf you want to register without affecting the entire runtime environment, you can add a namespace.\n\nWhen a namespace is provided, it will return a private `require()` method for you to load files with:\n```js\nconst tsx = require('tsx/cjs/api')\n\nconst api = tsx.register({\n    // Pass in a unique namespace\n    namespace: Date.now().toString()\n})\n\n// Pass in the request and the current file path\nconst loaded = api.require('./file.ts', __filename)\n\napi.unregister()\n```\n"
  },
  {
    "path": "docs/dev-api/register-esm.md",
    "content": "# ESM Register API\n\nThe ESM Register API allows you to manually register the enhancement at runtime. But note, this only affects ESM (`.mjs`/`.mts`, and `.js`/`.ts` when `package.json#type` is `module`).\n\n## Usage\n```js\nimport { register } from 'tsx/esm/api'\n\n// Register tsx enhancement\nconst unregister = register()\n\nawait import('./file.ts')\n\n// Unregister when needed\nunregister()\n```\n\n### Scoped registration\n\nIf you want to register without affecting the entire runtime environment, you can add a namespace.\n\nWhen a namespace is provided, it will return a private `import()` method for you to load files with:\n\n```js\nimport { register } from 'tsx/esm/api'\n\nconst api = register({\n    // Pass in a unique namespace\n    namespace: Date.now().toString()\n})\n\n// Pass in the request and the current file path\n// Since this is namespaced, it will not cache hit from prior imports\nconst loaded = await api.import('./file.ts', import.meta.url)\n\n// This is using the same namespace as above, so it will yield a cache hit\nconst loaded2 = await api.import('./file.ts', import.meta.url)\n\napi.unregister()\n```\n\n### Tracking loaded files\n\nDetect files that get loaded with the `onImport` hook. This can be useful when you want to track dependencies when setting up a watcher.\n\n```ts\nregister({\n    onImport: (file: string) => {\n        console.log(file) // 'file:///foo.ts'\n    }\n})\n```\n"
  },
  {
    "path": "docs/dev-api/ts-import.md",
    "content": "# `tsImport()`\n\nNative dynamic `import()` function to import TypeScript files (supports [top-level await](https://v8.dev/features/top-level-await)).\n\nUse this function for importing TypeScript files without adding TypeScript support to the entire runtime.\n\nThe current file path must be passed in as the second argument to resolve the import context.\n\nSince this is designed for one-time use, it does not cache loaded modules.\n\n## Usage\n\n### ESM\n\n```js\nimport { tsImport } from 'tsx/esm/api'\n\nconst loaded = await tsImport('./file.ts', import.meta.url)\n\n// If tsImport is used to load file.ts again,\n// it does not yield a cache-hit and re-loads it\nconst loadedAgain = await tsImport('./file.ts', import.meta.url)\n```\n\nIf you'd like to leverage module caching, see the [ESM scoped registration](/dev-api/register-esm.md) section.\n\n### CommonJS\n\n```js\nconst { tsImport } = require('tsx/esm/api')\n\nconst loaded = await tsImport('./file.ts', __filename)\n```\n\n## `tsconfig.json`\n\n### Custom `tsconfig.json` path\n```ts\ntsImport('./file.ts', {\n    parentURL: import.meta.url,\n    tsconfig: './custom-tsconfig.json'\n})\n```\n\n### Disable `tsconfig.json` lookup\n```ts\ntsImport('./file.ts', {\n    parentURL: import.meta.url,\n    tsconfig: false\n})\n```\n\n## Tracking loaded files\n\nDetect files that get loaded with the `onImport` hook:\n\n```ts\ntsImport('./file.ts', {\n    parentURL: import.meta.url,\n    onImport: (file: string) => {\n        console.log(file)\n        // file:///foo.ts\n    }\n})\n```\n"
  },
  {
    "path": "docs/dev-api/tsx-require.md",
    "content": "# `tsx.require()`\n\nNative `require()` function enhanced with TypeScript & ESM support.\n\nUse this function for importing TypeScript files in CommonJS mode without adding TypeScript support to the entire runtime.\n\nNote, the current file path must be passed in as the second argument to resolve the import context.\n\n::: warning Caveats\n\n- `import()` calls in the loaded files are not enhanced. Use [`tsImport()`](/dev-api/ts-import) instead.\n- Because it compiles ESM syntax to run in CommonJS mode, top-level await is not supported\n:::\n\n## Usage\n\n### CommonJS\n\n```js\nconst tsx = require('tsx/cjs/api')\n\nconst tsLoaded = tsx.require('./file.ts', __filename)\nconst tsFilepath = tsx.require.resolve('./file.ts', __filename)\n```\n\n### ESM\n\n```js\nimport { require } from 'tsx/cjs/api'\n\nconst tsLoaded = require('./file.ts', import.meta.url)\nconst tsFilepath = require.resolve('./file.ts', import.meta.url)\n```\n\n## Tracking loaded files\n\nBecause the CommonJS API tracks loaded modules in `require.cache`, you can use it to identify loaded files for dependency tracking. This can be useful when implementing a watcher.\n\n```js\nconst resolvedPath = tsx.require.resolve('./file', import.meta.url)\n\nconst collectDependencies = module => [\n    module.filename,\n    ...module.children.flatMap(collectDependencies)\n]\n\nconsole.log(collectDependencies(tsx.require.cache[resolvedPath]))\n// ['/file.ts', '/foo.ts', '/bar.ts']\n```\n"
  },
  {
    "path": "docs/faq.md",
    "content": "<script setup lang=\"ts\">\nimport ImageLink from './.vitepress/theme/components/ImageLink.vue';\n</script>\n\n# Frequently Asked Questions\n\n## How can I do ______ in _tsx_?\n\nWe understand that searching for answers about _tsx_ can be challenging due to its name. However, since _tsx_ is essentially an alias for `node` and adheres to TypeScript behavior, asking how to do something in _tsx_ might not be the best approach.\n\nInstead, consider these questions:\n- _\"How can I do ______ in Node.js?\"_\n- _\"How can I do ______ in TypeScript?\"_\n\nIf your question specifically relates to _tsx_, you can use the search feature in the documentation or [ask a question](#ask-a-question).\n\n\n## I found a bug in _tsx_. What should I do?\n\nIf you've confirmed that the bug is in _tsx_, please file an issue in the _tsx_ GitHub repository. Make sure to include a minimal reproduction of the bug.\n\n<a class=\"button bug-report\" href=\"https://github.com/privatenumber/tsx/issues/new?assignees=&labels=bug%2Cpending+triage&projects=&template=bug-report.yml\" target=\"_blank\">\n\tFile a bug report ↗\n</a>\n\n## Who uses _tsx_?\n\n_tsx_ is recognized by both [Node.js](https://nodejs.org/en/learn/getting-started/nodejs-with-typescript#running-typescript-code-with-tsx) and [TypeScript](https://www.typescriptlang.org/docs/handbook/modules/guides/choosing-compiler-options.html#im-using-tsx) as a popular tool for running TypeScript code. It is widely adopted, as indicated by its npm download stats: <a href=\"https://npm.im/tsx\"><img class=\"inline-block\" src=\"https://badgen.net/npm/dm/tsx\"></a>.\n\n### Companies\n\n<div class=\"logos dark-zebra-pattern\">\n<ImageLink\n\talt=\"Vercel\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Avercel&type=code\"\n\timg-src=\"/logos/vercel.svg\"\n/>\n<ImageLink\n\talt=\"Google\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Agoogle&type=code\"\n\timg-src=\"/logos/google.svg\"\n/>\n<ImageLink\n\talt=\"GitHub\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Agithub&type=code\"\n\timg-src=\"/logos/github.svg\"\n/>\n<ImageLink\n\talt=\"Square\"\n\thref=\"https://github.com/square\"\n\timg-src=\"/logos/square.svg\"\n/>\n<ImageLink\n\talt=\"Supabase\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Asupabase&type=code\"\n\timg-src=\"/logos/supabase.svg\"\n/>\n<ImageLink\n\talt=\"Astro\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Awithastro&type=code\"\n\timg-src=\"/logos/astro.svg\"\n/>\n<ImageLink\n\talt=\"OpenAI\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aopenai&type=code\"\n\timg-src=\"/logos/openai.svg\"\n/>\n<ImageLink\n\talt=\"IBM\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aibm&type=code\"\n\timg-src=\"/logos/ibm.svg\"\n/>\n<ImageLink\n\talt=\"Codecov\"\n\thref=\"https://github.com/codecov\"\n\timg-src=\"/logos/codecov.svg\"\n/>\n<ImageLink\n\talt=\"Amazon AWS\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aaws+OR+org%3Aawslabs&type=code\"\n\timg-src=\"/logos/aws.svg\"\n/>\n<ImageLink\n\talt=\"Sentry\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Agetsentry&type=code\"\n\timg-src=\"/logos/sentry.svg\"\n/>\n<ImageLink\n\talt=\"Microsoft\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Amicrosoft&type=code\"\n\timg-src=\"/logos/microsoft.svg\"\n/>\n<ImageLink\n\talt=\"Meta\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Afacebook&type=code\"\n\timg-src=\"/logos/meta.svg\"\n/>\n<ImageLink\n\talt=\"Alibaba\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aalibaba&type=code\"\n\timg-src=\"/logos/alibaba.svg\"\n/>\n<ImageLink\n\talt=\"Mozilla\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Amozilla&type=code\"\n\timg-src=\"/logos/mozilla.svg\"\n/>\n<ImageLink\n\talt=\"Figma\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Afigma&type=code\"\n\timg-src=\"/logos/figma.svg\"\n/>\n<ImageLink\n\talt=\"Cloudflare\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Acloudflare&type=code\"\n\timg-src=\"/logos/cloudflare.svg\"\n/>\n<ImageLink\n\talt=\"Salesforce\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Asalesforce&type=code\"\n\timg-src=\"/logos/salesforce.svg\"\n/>\n</div>\n\n### Projects\n<div class=\"logos dark-zebra-pattern\">\n<ImageLink\n\talt=\"Node.js\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Anodejs&type=code\"\n\timg-src=\"/logos/nodejs.svg\"\n/>\n<ImageLink\n\talt=\"Electron\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aelectron&type=code\"\n\timg-src=\"/logos/electron.svg\"\n/>\n<ImageLink\n\talt=\"Vite\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Avitejs&type=code\"\n\timg-src=\"/logos/vite.svg\"\n/>\n<ImageLink\n\talt=\"Mermaid\"\n\thref=\"https://github.com/mermaid-js/mermaid/blob/3809732e48a0822fad596d0815a6dc0e166dda94/package.json#L121\"\n\timg-src=\"/logos/mermaid.svg\"\n/>\n<ImageLink\n\talt=\"Vue.js\"\n\thref=\"https://github.com/vuejs/core/blob/70641fc0deb857464d24aa7ab7eaa18e2a855146/package.json#L110\"\n\timg-src=\"/logos/vue.svg\"\n/>\n<ImageLink\n\talt=\"11ty\"\n\thref=\"https://www.11ty.dev/docs/languages/typescript/\"\n\timg-src=\"/logos/11ty.svg\"\n/>\n<ImageLink\n\talt=\"Vitest\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Avitest-dev&type=code\"\n\timg-src=\"/logos/vitest.svg\"\n/>\n<ImageLink\n\talt=\"date-fns\"\n\thref=\"https://github.com/date-fns/date-fns/blob/5c1adb5369805ff552737bf8017dbe07f559b0c6/package.json#L6123\"\n\timg-src=\"/logos/date-fns.svg\"\n/>\n<ImageLink\n\talt=\"Cheerio\"\n\thref=\"https://github.com/cheeriojs/cheerio/blob/d0b3c2f6b57cd1f835741175d463963266be0eef/package.json#L99\"\n\timg-src=\"/logos/cheerio.svg\"\n/>\n<ImageLink\n\talt=\"Zod\"\n\thref=\"https://github.com/colinhacks/zod/blob/7173d0bcc2105777102e22d36a2866196e2830f3/package.json#L45\"\n\timg-src=\"/logos/zod.svg\"\n/>\n<ImageLink\n\talt=\"WebDriverIO\"\n\thref=\"https://github.com/webdriverio/webdriverio/blob/5955cda26a538a12b10d686a394beb1b109fe49d/package.json#L122\"\n\timg-src=\"/logos/webdriverio.svg\"\n/>\n<ImageLink\n\talt=\"Knip\"\n\thref=\"https://github.com/webpro-nl/knip/blob/b9b8f4da3dcbff1af309bfbb7890bb9ec36124f9/packages/knip/package.json#L48\"\n\timg-src=\"/logos/knip.svg\"\n/>\n<ImageLink\n\talt=\"ArkType\"\n\thref=\"https://github.com/arktypeio/arktype/blob/1820e86e93e1ccaabda7f8de28fb7f04320d6fc8/package.json#L59\"\n\timg-src=\"/logos/arktype.svg\"\n/>\n<ImageLink\n\talt=\"Prisma\"\n\thref=\"https://github.com/prisma/prisma/blob/f19a3e28a37327eb0a5e45941c0e4abf3dbab136/package.json#L94\"\n\timg-src=\"/logos/prisma.svg\"\n/>\n</div>\n\nTo find more examples of where & how _tsx_ is used, [search on GitHub](https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22&type=code).\n\n## How does _tsx_ compare to [`ts-node`](https://github.com/TypeStrong/ts-node)?\n\n`tsx` and `ts-node` are both tools for running TypeScript in Node.js, each offering different approaches to suit user preferences.\n\n**Installation**\n\n- **tsx**: Can be used without installation (via `npx tsx ./script.ts`) and comes as a single binary with no peer dependencies.\n- **ts-node**: Requires installation of TypeScript or SWC as peer dependencies.\n\n**Configuration**\n\n- **tsx**: Works out of the box without needing a `tsconfig.json` file, making it easy for beginners.\n- **ts-node**: May require initial setup and configuration.\n\n**Defaults**\n\n- **tsx**: Uses sensible defaults based on file imports and Node.js version, reducing the need for certain `tsconfig.json` settings.\n- **ts-node**: Relies on TypeScript's defaults, which might need adjusting.\n\n**Module Support**\n\n- **tsx**: Automatically adapts between CommonJS and ESM modules, supporting `require()` for ESM modules.\n- **ts-node**: Provides module support but may need configuration for certain scenarios.\n\n**Syntax and Features**\n\n- **tsx**: Supports new JS & TS syntax and features based on Node.js version and includes support for `tsconfig.json` paths.\n- **ts-node**: Uses the TypeScript compiler and may require additional settings for certain features.\n\n**Speed**\n\n- **tsx**: Uses [esbuild](https://esbuild.github.io/faq/#:~:text=typescript%20benchmark) for fast compilation and does not perform type checking.\n- **ts-node**: Uses the TypeScript compiler by default, with an option to use the SWC compiler for faster performance.\n\n**Watcher**\n\nAs a DX bonus, _tsx_ also comes with [Watch mode](/watch-mode.md) to help you iterate faster!\n\nFor a detailed technical comparison, refer to this [exhaustive comparison](https://github.com/privatenumber/ts-runtime-comparison) between `tsx`, `ts-node`, and other runtimes.\n\n## Can/should _tsx_ be used in production?\n\nDeciding whether to use _tsx_ in production depends on your specific needs and risk tolerance. Here are a few points to consider:\n\n- _tsx_ is simply a Node.js enhancement, so you can generally expect a similar level of stability.\n- _tsx_ uses [esbuild](https://esbuild.github.io) for transforming TypeScript and ESM. Although esbuild is already adopted in many production ready tools, keep in mind that it technically hasn't reached a stable release yet.\n\nHere are some questions to help guide your decision:\n\n- What are the benefits versus the costs of using _tsx_ in production? Are there performance improvements?\n- Does _tsx_ run your code as expected? Are there any differences between development and production environments?\n- Can you rely on this open-source project and its maintainers? Consider [sponsoring](https://github.com/sponsors/privatenumber/sponsorships?tier_id=416984) the project to support its growth and stability.\n\nUltimately, it's a decision you'll need to make based on your specific production requirements and comfort level with potential risks.\n\n---\n\n# Ask a question\n\n_tsx_ offers support via [Discussions](https://github.com/pvtnbr/tsx/discussions) for [sponsors](https://github.com/sponsors/privatenumber/sponsorships?tier_id=416984). If you're a sponsor, feel free to ask more questions there!\n\n<style scoped>\n.bug-report {\n\t@apply\n\t\ttext-sm\n\t\ttext-white\n\t\thover:text-white\n\t\tbg-blue-500\n\t\thover:bg-blue-600\n\t\t;\n}\n\n.logos {\n\t@apply\n\t\tflex\n\t\tflex-wrap\n\t\tgap-x-4\n\t\tgap-y-6\n\t\tjustify-around\n\t\tmy-4\n\t\tpy-6\n\t\tpx-4\n\t\tdark:bg-zinc-800;\n\n\t& :deep(img) {\n\t\t@apply h-10;\n\t}\n}\n</style>\n\n"
  },
  {
    "path": "docs/getting-started.md",
    "content": "# Getting started\n\n### Prerequisites\n\nBefore you can start using _tsx_, ensure that you have [Node.js installed](https://nodejs.org/en/download/). _tsx_ is designed to be compatible with all [maintained versions](https://endoflife.date/nodejs) of Node.js.\n\n## Quickstart\n\n`tsx` can be executed with [npx](https://docs.npmjs.com/cli/commands/npx/)—a tool to run npm packages without installing them.\n\nIn your command-line, simply pass in a TypeScript file you'd like to run. It's that simple!\n\n```sh\nnpx tsx ./script.ts\n```\n\n## Project installation\n\nTo install `tsx` as a project development dependency, run the following command in your project directory:\n\n::: code-group\n```sh [npm]\n$ npm install -D tsx\n```\n\n```sh [pnpm]\n$ pnpm add -D tsx\n```\n\n```sh [yarn]\n$ yarn add -D tsx\n```\n:::\n\n#### Using `tsx`\n\nOnce installed, you can invoke it with your package manager while in the project directory:\n\n::: code-group\n```sh [npm]\n$ npx tsx ./file.ts\n```\n\n```sh [pnpm]\n$ pnpm tsx ./file.ts\n```\n\n```sh [yarn]\n$ yarn tsx ./file.ts\n```\n:::\n\n#### Using it in `package.json#scripts`\n\nProject commands are usually organized in the [`package.json#scripts`](https://docs.npmjs.com/cli/v10/using-npm/scripts) object.\n\nIn the `scripts` object, you can reference `tsx` directly without `npx`:\n\n```js\n// package.json\n{\n    \"scripts\": {\n        \"start\": \"tsx ./file.ts\"// [!code highlight]\n    }\n}\n```\n\n## Global installation\n\nIf you want to use `tsx` anywhere on your computer (without [`npx`](https://docs.npmjs.com/cli/commands/npx/)), install it globally:\n\n::: code-group\n```sh [npm]\n$ npm install -g tsx\n```\n\n```sh [pnpm]\n$ pnpm add -g tsx\n```\n\n```sh [yarn]\nYarn 2 doesn't support global installation\nhttps://yarnpkg.com/migration/guide#use-yarn-dlx-instead-of-yarn-global\n```\n:::\n\nThis allows you to call `tsx` directly:\n\n```sh\ntsx file.ts\n```\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\noutline: false\n---\n\n<div class=\"mb-10\">\n<img src=\"/logo-dark.svg\" width=\"150\" class=\"light:hidden\" alt=\"tsx: TypeScript Execute\">\n<img src=\"/logo-light.svg\" width=\"150\" class=\"dark:hidden\" alt=\"tsx: TypeScript Execute\">\n</div>\n\n# TypeScript Execute <span class=\"font-normal\">(_tsx_)</span>\n\n_tsx_ stands for _TypeScript Execute_ and it's a Node.js enhancement to run [TypeScript](https://www.typescriptlang.org).\n\nFor starters, think of `tsx` as an alias to `node` and use it the same way:\n\n<div class=\"tsx-before-after\">\n\n```sh\nnode file.js\n```\n<span class=\"hidden sm:block\">→</span>\n<span class=\"sm:hidden\">↓</span>\n```sh\ntsx file.ts\n```\n</div>\n\nYou can pass in Node CLI flags and JS files too:\n```sh\ntsx --env-file=.env ./file.js\n```\n\n## Features\n\n### Seamless TypeScript execution\n\nRun TypeScript code without worrying about configuration!\n\n_tsx_ runs your TypeScript code with modern and sensible defaults, making it user-friendly and especially great for beginners.\n\n### Seamless CJS ↔ ESM imports\n\nNo need to wonder whether a package is CommonJS or ESM again.\n\nIf you've encountered the `ERR_REQUIRE_ESM` error in Node, you'll never see it again!\n\n### Watch mode\n\nAs a DX bonus, _tsx_ comes with [Watch mode](/watch-mode.md) to re-run your files whenever you save them.\n\nIterate on your code faster and boost productivity!\n\n---\n\n<a href=\"/faq#who-uses-tsx\" class=\"!no-underline\">Who uses _tsx_?</a>\n\n<Marquee class=\"mt-6 dark:bg-zinc-800 dark-zebra-pattern py-6\" :velocity=\"20\">\n<div class=\"flex gap-6 items-center min-w-full\">\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Vercel\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Avercel&type=code\"\n\timg-src=\"/logos/vercel.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Google\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Agoogle&type=code\"\n\timg-src=\"/logos/google.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"GitHub\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Agithub&type=code\"\n\timg-src=\"/logos/github.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Figma\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Afigma&type=code\"\n\timg-src=\"/logos/figma.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Square\"\n\thref=\"https://github.com/square\"\n\timg-src=\"/logos/square.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Microsoft\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Amicrosoft&type=code\"\n\timg-src=\"/logos/microsoft.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"OpenAI\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aopenai&type=code\"\n\timg-src=\"/logos/openai.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Amazon AWS\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aaws+OR+org%3Aawslabs&type=code\"\n\timg-src=\"/logos/aws.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Meta\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Afacebook&type=code\"\n\timg-src=\"/logos/meta.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"IBM\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aibm&type=code\"\n\timg-src=\"/logos/ibm.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Alibaba\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Aalibaba&type=code\"\n\timg-src=\"/logos/alibaba.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Mozilla\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Amozilla&type=code\"\n\timg-src=\"/logos/mozilla.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Cloudflare\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Acloudflare&type=code\"\n\timg-src=\"/logos/cloudflare.svg\"\n/>\n<ImageLink\n\tclass=\"h-12\"\n\talt=\"Salesforce\"\n\thref=\"https://github.com/search?q=path%3Apackage.json+%22%5C%22tsx%5C%22%3A+%5C%22%22+org%3Asalesforce&type=code\"\n\timg-src=\"/logos/salesforce.svg\"\n/>\n</div>\n</Marquee>\n\n## About the project\n\nThe idea for _tsx_ came about during a time when the Node.js ecosystem was getting fragmented due to the release of [ES Modules (ESM)](https://nodejs.org/api/esm.html). As packages migrated to ESM, projects struggled to reconcile their CommonJS apps with ESM dependencies.\n\nBack then, _ts-node_ was the go-to tool for running TypeScript in Node.js, but it lacked ESM support and was quite complicated to use. We noticed several open-source tools using esbuild to run TypeScript in Node.js and decided to bring these efforts together into one simple, cohesive project.\n\n**_tsx_ is designed to simplify your TypeScript experience.** It enhances Node.js with TypeScript support in both CommonJS and ESM modes, allowing you to switch between them seamlessly. It also supports `tsconfig.json` paths and includes a Watch mode to make development even easier.\n\nRight now, the _tsx_ project development relies on user donations, which isn't sustainable in the long run. To keep _tsx_ reliable and growing, we need funding to cover maintenance and development costs.\n\nIf your company uses _tsx_ and would like to support the project, consider [sponsoring us](https://github.com/sponsors/privatenumber/sponsorships?pay_prorated=false&tier_id=388346)—in return we'll put up your logo + link!\n\n## Sponsors\n\n<p align=\"center\">\n\t<Sponsors />\n\t<a class=\"button sponsor-button mt-10 mx-auto\" href=\"https://github.com/sponsors/privatenumber/sponsorships?tier_id=416984\" target=\"_blank\">\n\t\tBecome a sponsor\n\t</a>\n</p>\n\n<style scoped>\n.tsx-before-after {\n\t@apply\n\t\tflex\n\t\tjustify-between\n\t\tgap-4\n\t\titems-center\n\t\tflex-wrap\n\t\tsm:flex-nowrap;\n\n\t> * {\n\t\t@apply\n\t\t\tw-full\n\t\t\ttext-center\n\t\t\tm-0;\n\t}\n\n\t> p {\n\t\t@apply sm:w-auto;\n\t}\n}\n\n.sponsor-button {\n\t@apply\n\t\ttext-white\n\t\thover:text-white\n\t\tbg-pink-500\n\t\thover:bg-pink-600\n\t\t;\n}\n</style>\n\n<script setup lang=\"ts\">\nimport ImageLink from './.vitepress/theme/components/ImageLink.vue';\nimport Marquee from './.vitepress/theme/components/Marquee.vue';\nimport Sponsors from './.vitepress/theme/components/Sponsors.vue';\n</script>\n"
  },
  {
    "path": "docs/learn.md",
    "content": "# Learning resources\n\nTypeScript can be difficult to get started with and _tsx_ is all about lowering that barrier of entry.\n\nHere are some great resources for your reference.\n\n::: info\n\nThis page is currently a work in progress.\n\nIf you're a TypeScript educator or you know any TS courses that use tsx, [let us know](/contact)!\n:::\n\n## Documentation\n\n- [TypeScript documentation](https://www.typescriptlang.org/docs/)\n\n- [Node.js documentation](https://nodejs.org/docs/latest/api/)\n"
  },
  {
    "path": "docs/node-enhancement.md",
    "content": "# Node.js enhancement\n\n## Swap `node` for `tsx`\n\n`tsx` is a drop-in replacement for `node`, meaning you can use it the exact same way (supports all [command-line flags](https://nodejs.org/api/cli.html)).\n\nIf you have an existing `node` command, simply substitute it with `tsx`.\n\n```sh\nnode --no-warnings --env-file=.env ./file.js\n```\n<p class=\"text-center\">↓</p>\n\n```sh\ntsx --no-warnings --env-file=.env ./file.js\n```\n\n::: warning Node.js version matters\nUnder the hood, `tsx` calls `node`. This means the Node.js features supported in `tsx` depend on the Node.js version you have installed.\n:::\n\n## Flag & arguments positioning\n\nJust like with `node`, correctly positioning flags and arguments is important when using `tsx`.\n\nPlace _tsx_ flags immediately after `tsx`, and place flags and arguments for your script after the script path.\n\n```sh\ntsx [tsx flags] ./file.ts [flags & arguments for file.ts]\n```\n\n## TypeScript REPL\n\n_tsx_ extends the Node.js REPL to support TypeScript, allowing interactive coding sessions directly in TypeScript.\n\n```sh\ntsx\n```\n\n::: info What is the Node.js REPL?\nThe [Node.js REPL](https://nodejs.org/en/learn/command-line/how-to-use-the-nodejs-repl) is an interactive prompt that immediately executes input code, ideal for learning and experimenting. _tsx_ enhances this tool by adding TypeScript support.\n:::\n\n## Test runner\n\n_tsx_ enhances the Node.js built-in [test runner](https://nodejs.org/api/test.html) with TypeScript support. You can use it the same way:\n\n```sh\ntsx --test\n```\n\nIt will automatically recognize test files with TypeScript extensions:\n- `**/*.test.?[cm][jt]s`\n- `**/*-test.?[cm][jt]s`\n- `**/*_test.?[cm][jt]s`\n- `**/test-*.?[cm][jt]s`\n- `**/test.?[cm][jt]s`\n- `**/test/**/*.?[cm][jt]s`\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n\t\"name\": \"docs\",\n\t\"private\": true,\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"dev\": \"vitepress dev --open\",\n\t\t\"build\": \"vitepress build\",\n\t\t\"prepare\": \"node ./scripts/hash-class-names.js ./node_modules/vitepress/dist/client/theme-default\",\n\t\t\"preview\": \"vitepress preview\"\n\t},\n\t\"devDependencies\": {\n\t\t\"autoprefixer\": \"^10.4.21\",\n\t\t\"tailwindcss\": \"^3.4.17\",\n\t\t\"vitepress\": \"^1.6.4\"\n\t}\n}"
  },
  {
    "path": "docs/postcss.config.js",
    "content": "export default {\n\tplugins: {\n\t\ttailwindcss: {},\n\t\tautoprefixer: {},\n\t},\n};\n"
  },
  {
    "path": "docs/scripts/hash-class-names.js",
    "content": "import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nconst TARGET_CLASSES = ['VPDocAside'];\nconst ALLOWED_EXTENSIONS = new Set(['.css', '.js', '.vue']);\nconst generateHash = () => Math.random().toString(36).slice(2, 8);\n\nconst listFilesRecursive = async (directory) => {\n\tconst entries = await fs.readdir(directory, { withFileTypes: true });\n\tconst paths = await Promise.all(\n\t\tentries.map(async (entry) => {\n\t\t\tconst resolved = path.resolve(directory, entry.name);\n\t\t\treturn entry.isDirectory() ? listFilesRecursive(resolved) : resolved;\n\t\t}),\n\t);\n\treturn paths.flat().filter(file => ALLOWED_EXTENSIONS.has(path.extname(file)));\n};\n\nconst rewriteFiles = async (filePaths, classNames) => {\n\tconst classMap = new Map();\n\tclassNames.sort((a, b) => b.length - a.length).forEach((name) => {\n\t\tclassMap.set(name, `${name}-${generateHash()}`);\n\t});\n\tawait Promise.all(\n\t\tfilePaths.map(async (filePath) => {\n\t\t\tlet content = await fs.readFile(filePath, 'utf8');\n\t\t\tconst original = content;\n\t\t\tclassMap.forEach((replacement, originalName) => {\n\t\t\t\tconst selectorPattern = new RegExp(`(?<![-_\\\\w])\\\\.${originalName}(?![-_\\\\w])`, 'g');\n\t\t\t\tcontent = content.replace(selectorPattern, `.${replacement}`);\n\t\t\t});\n\t\t\tconst classAttributePattern = /(class(?:Name)?\\s*=\\s*)([\"'])(.*?)\\2/g;\n\t\t\tcontent = content.replaceAll(classAttributePattern, (_whole, attribute, quote, value) => {\n\t\t\t\tconst updated = String(value).split(/\\s+/).map(cls => classMap.get(cls) || cls).join(' ');\n\t\t\t\treturn `${attribute}${quote}${updated}${quote}`;\n\t\t\t});\n\t\t\tif (content !== original) { await fs.writeFile(filePath, content, 'utf8'); }\n\t\t}),\n\t);\n};\n\nconst input = process.argv[2];\nif (!input) { throw new Error('Input directory is required.'); }\nconst directory = path.resolve(input);\nconst stats = await fs.stat(directory).catch(() => null);\nif (!stats?.isDirectory()) { throw new Error('Input must be a valid directory.'); }\nconst filePaths = await listFilesRecursive(directory);\nawait rewriteFiles(filePaths, TARGET_CLASSES);\n"
  },
  {
    "path": "docs/shell-scripts.md",
    "content": "# Shell scripts\n\nYou can write a shell script in TypeScript by specifying _tsx_ in the [hashbang](https://bash.cyberciti.biz/guide/Shebang). The hashbang tells the shell how to run the script, making it executable.\n\n### Project scripts\n\nIf `tsx` is installed in your project, use your package manager to reference _tsx_:\n\n::: code-group\n```ts [npm]\n#!/usr/bin/env -S npx tsx\n\nconsole.log('argv:', process.argv.slice(2))\n```\n\n```ts [pnpm]\n#!/usr/bin/env -S pnpm tsx\n\nconsole.log('argv:', process.argv.slice(2))\n```\n\n```ts [yarn]\n#!/usr/bin/env -S yarn tsx\n\nconsole.log('argv:', process.argv.slice(2))\n```\n:::\n\nMake the file executable:\n```sh\nchmod +x ./file.ts\n```\n\nNow, you can run `./file.ts` directly:\n```sh\n./file.ts hello world\n# Output: argv: [ 'hello', 'world' ]\n```\n\n\n### Global scripts\n\nIf `tsx` is installed globally, you can reference `tsx` directly in the hashbang:\n\n_file.ts_:\n```ts\n#!/usr/bin/env tsx\n\nconsole.log('argv:', process.argv.slice(2))\n```\n\nDon't forget to `chmod` the file to make it executable!\n"
  },
  {
    "path": "docs/tailwind.config.js",
    "content": "/** @type {import('tailwindcss').Config} */\nexport default {\n\tcontent: [\n\t\t'**/*.md',\n\t\t'.vitepress/**/*.vue',\n\t],\n\tdarkMode: 'selector',\n\tplugins: [\n\t\t({ addVariant }) => addVariant('light', 'html:not(.dark) &'),\n\t],\n};\n"
  },
  {
    "path": "docs/typescript.md",
    "content": "# TypeScript\n\n_tsx_ does not type check your code on its own and expects it to be handled separately. While _tsx_ doesn’t require TypeScript to be installed, and the type checks provided by your IDE might suffice for quick scripts, it is highly recommended to include a type checking step in your projects.\n\n\n## Development workflow\n\nType checking is important but it can be time-consuming and expensive to do on every run.\n\n`tsx` alleviates this problem by allowing you to execute TypeScript code directly without being blocked by type errors. Modern IDEs like VSCode provide real-time type checking via [IntelliSense](https://code.visualstudio.com/docs/languages/typescript), reducing the need for manual type checks. This workflow lets you iterate faster on functionality and treat type errors as linting errors rather than compilation requirements.\n\nTo incorporate type checking, include it with other linters (e.g. ESLint) in pre-commit hooks or CI checks.\n\n## Installation\n\nStart by installing the following in your project:\n\n- [`typescript`](https://npmjs.com/package/typescript) to type-check with the `tsc` CLI command\n- [`@types/node`](https://npmjs.com/package/@types/node) to provide TypeScript with Node.js API types\n\n::: code-group\n```sh [npm]\n$ npm install -D typescript @types/node\n```\n\n```sh [pnpm]\n$ pnpm add -D typescript @types/node\n```\n\n```sh [yarn]\n$ yarn add -D typescript @types/node\n```\n:::\n\n## tsconfig.json\n[`tsconfig.json`](https://www.typescriptlang.org/tsconfig/) is the configuration file used by TypeScript.\n\n### Recommendation\n\nHere's the recommended configuration to make type-checking behave consistently.\n\n```jsonc\n{\n\t\"compilerOptions\": {\n\n\t\t// Treat files as modules even if it doesn't use import/export\n\t\t\"moduleDetection\": \"force\",\n\n\t\t// Ignore module structure\n\t\t\"module\": \"Preserve\",\n\n\t\t// Allow JSON modules to be imported\n\t\t\"resolveJsonModule\": true,\n\n\t\t// Allow JS files to be imported from TS and vice versa\n\t\t\"allowJs\": true,\n\n\t\t// Use correct ESM import behavior\n\t\t\"esModuleInterop\": true,\n\n\t\t// Disallow features that require cross-file awareness\n\t\t\"isolatedModules\": true,\n\t},\n}\n```\n\n::: tip\nIt's also recommended to enable [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) which requires you to write your type imports & exports using explicit syntax. Refactoring may be necessary.\n\n[Read more](https://www.typescriptlang.org/docs/handbook/modules/reference.html#type-only-imports-and-exports)\n:::\n\n### JSX\n\n_tsx_ respects the following configurations for JSX in `.jsx` and `.tsx` files:\n\n- [`jsx`](https://www.typescriptlang.org/tsconfig/#jsx)\n- [`jsxFactory`](https://www.typescriptlang.org/tsconfig/#jsxFactory)\n- [`jsxFragmentFactory`](https://www.typescriptlang.org/tsconfig/#jsxFragmentFactory)\n- [`jsxImportSource`](https://www.typescriptlang.org/tsconfig/#jsxImportSource)\n\n\n## Custom `tsconfig.json` path\nBy default, `tsconfig.json` is detected from the current working directory.\n\nTo pass in a `tsconfig.json` file from a custom path, use the `--tsconfig` flag:\n\n```sh\ntsx --tsconfig ./path/to/tsconfig.custom.json ./file.ts\n```\n\n## Type checking\n\nUse TypeScript to type check:\n```sh\ntsc --noEmit\n```\n\n(You can omit `--noEmit` if it's already specified in your `tsconfig.json`)\n\n### `package.json` script\nSince `tsc` is also a compiler, you can add a script to your `package.json` to specify that it's used for type checking only:\n```js\n// package.json\n{\n    // ...\n\n    \"scripts\": {\n        \"type-check\": \"tsc --noEmit\"// [!code ++]\n    },\n\n    // ...\n}\n```\n\n### Pre-commit hook\nTo type check on pre-commit, use [simple-git-hooks](https://www.npmjs.com/package/simple-git-hooks):\n```js\n// package.json\n{\n    // ...\n\n    \"scripts\": {\n        // Register Git hooks on `npm install`\n        \"prepare\": \"simple-git-hooks\"// [!code ++]\n    },\n    \"simple-git-hooks\": {\n        \"pre-commit\": \"npm run type-check\",// [!code ++]\n\n        // Or if you have multiple commands\n        \"pre-commit\": [\n            \"npm run lint\",\n            \"npm run type-check\"// [!code ++]\n        ]\n    }\n}\n```\n\n## Compiler limitations\n_tsx_ uses [esbuild](https://esbuild.github.io) to compile TypeScript and ESM, so it shares some of the same limitations:\n\n- Compatibility with `eval()` is not preserved\n- Only [certain `tsconfig.json` properties](https://esbuild.github.io/content-types/#tsconfig-json) are supported\n\t- [`emitDecoratorMetadata`](https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata) is not supported\n\nFor detailed information, refer to esbuild's [JavaScript caveats](https://esbuild.github.io/content-types/#javascript-caveats) and [TypeScript caveats](https://esbuild.github.io/content-types/#typescript-caveats) documentation.\n\n"
  },
  {
    "path": "docs/vscode.md",
    "content": "# VS Code debugging\n\nIf you use [VS Code](https://code.visualstudio.com), you can configure it to use _tsx_ to enhance your debugging experience.\n\nTo learn more about VS Code configuration, refer to the [_Launch Configuration_](https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_launch-configuration) documentation.\n\n## Setup\n1. Create the config file\n\n\tCreate a launch configuration file in your project at `.vscode/launch.json`:\n\t```json5\n\t{\n\t    \"version\": \"0.2.0\",\n\t    \"configurations\": [\n\t        /*\n\t         * Each config in this array corresponds to an option\n\t         * in the debug drop-down\n\t         */\n\t    ],\n\t}\n\t```\n\n2. Pick and choose debugging methods\n\n::: details Method 1: Run _tsx_ from inside VSCode\n\n1. Add the following configuration to the `configurations` array in `.vscode/launch.json`:\n\t```json5\n\t{\n\t    \"name\": \"tsx\",\n\t    \"type\": \"node\",\n\t    \"request\": \"launch\",\n\n\t    // Debug current file in VSCode\n\t    \"program\": \"${file}\",\n\n\t    /*\n\t     * Path to tsx binary\n\t     * Assuming locally installed\n\t     */\n\t    \"runtimeExecutable\": \"tsx\",\n\n\t    /*\n\t     * Open terminal when debugging starts (Optional)\n\t     * Useful to see console.logs\n\t     */\n\t    \"console\": \"integratedTerminal\",\n\t    \"internalConsoleOptions\": \"neverOpen\",\n\n\t    // Files to exclude from debugger (e.g. call stack)\n\t    \"skipFiles\": [\n\t        // Node.js internal core modules\n\t        \"<node_internals>/**\",\n\n\t        // Ignore all dependencies (optional)\n\t        \"${workspaceFolder}/node_modules/**\",\n\t    ],\n\t}\n\t```\n\n2. In VSCode, open the JS/TS file you want to run\n\n3. Go to VSCode's debug panel, select \"tsx\" in the drop down, and hit the play button (<kbd>F5</kbd>).\n\n:::\n\n::: details Method 2: Attach the VS Code debugger to a running Node.js process\n\n> This method works for any Node.js process like _tsx_, and is not specific to _tsx_.\n\n1. Add the following configuration to the `configurations` array in `.vscode/launch.json`:\n\t```json\n\t{\n\t    \"name\": \"Attach to process\",\n\t    \"type\": \"node\",\n\t    \"request\": \"attach\",\n\t    \"port\": 9229,\n\t    \"skipFiles\": [\n\t        // Node.js internal core modules\n\t        \"<node_internals>/**\",\n\n\t        // Ignore all dependencies (optional)\n\t        \"${workspaceFolder}/node_modules/**\",\n\t    ],\n\t}\n\t```\n2. Run _tsx_ with [`--inspect-brk`](https://nodejs.org/api/cli.html#--inspect-brkhostport) in a terminal window:\n\n\t```sh\n\ttsx --inspect-brk ./your-file.ts \n\t```\n\n3. Go to VSCode's debug panel, select \"Attach to process\" in the drop down, and hit the play button (<kbd>F5</kbd>).\n:::\n"
  },
  {
    "path": "docs/watch-mode.md",
    "content": "# Watch mode\n\n::: warning Not to be confused with [Node's Watch mode](https://nodejs.org/docs/latest/api/cli.html#--watch)\n_tsx_ introduced _Watch mode_ before Node.js released the `--watch` flag in [v18.11.0](https://github.com/nodejs/node/releases/tag/v18.11.0). Although it is similar in functionality, it does not yet match the robustness of _tsx_'s Watch mode.\n:::\n\n## Overview\n\nWatch mode will automatically re-run your script whenever any of its dependencies are changed.\n\n```sh\ntsx watch ./file.ts\n```\n\n## Watch behavior\n\nBy default, _tsx_ watches all imported files, except those in the following directories:\n- `node_modules`\n- `bower_components`\n- `vendor`\n- `dist`\n- Hidden directories (`.*`)\n\n## Customizing watched files\n\n### Including files to watch\n\nTo include specific files or directories to watch, use the `--include` flag:\n\n```sh\ntsx watch --include ./other-dep.txt --include \"./other-deps/*\" ./file.ts\n```\n\n\n### Excluding files from watch\nTo exclude specific files from being watched, use the `--exclude` flag:\n\n```sh\ntsx watch --exclude ./ignore-me.js --exclude ./ignore-me-too.js ./file.ts\n```\n\n### Using glob patterns\n\nGlob patterns allow you to define a set of files or directories to ignore. To prevent your shell from expanding the glob patterns, wrap them in quotes:\n\n```sh\ntsx watch --exclude \"./data/**/*\" ./file.ts\n```\n\n## Tips\n\n- Press <kbd>Return</kbd> to manually rerun the script.\n- Use `--clear-screen=false` to prevent the screen from clearing on rerun.\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"name\": \"tsx\",\n\t\"version\": \"0.0.0-semantic-release\",\n\t\"description\": \"TypeScript Execute (tsx): Node.js enhanced with esbuild to run TypeScript & ESM files\",\n\t\"keywords\": [\n\t\t\"cli\",\n\t\t\"runtime\",\n\t\t\"node\",\n\t\t\"cjs\",\n\t\t\"commonjs\",\n\t\t\"esm\",\n\t\t\"typescript\",\n\t\t\"typescript runner\"\n\t],\n\t\"license\": \"MIT\",\n\t\"repository\": \"privatenumber/tsx\",\n\t\"author\": {\n\t\t\"name\": \"Hiroki Osame\",\n\t\t\"email\": \"hiroki.osame@gmail.com\"\n\t},\n\t\"files\": [\n\t\t\"dist\"\n\t],\n\t\"type\": \"module\",\n\t\"bin\": \"./dist/cli.mjs\",\n\t\"exports\": {\n\t\t\"./package.json\": \"./package.json\",\n\t\t\".\": \"./dist/loader.mjs\",\n\t\t\"./patch-repl\": \"./dist/patch-repl.cjs\",\n\t\t\"./cjs\": \"./dist/cjs/index.cjs\",\n\t\t\"./cjs/api\": {\n\t\t\t\"import\": {\n\t\t\t\t\"types\": \"./dist/cjs/api/index.d.mts\",\n\t\t\t\t\"default\": \"./dist/cjs/api/index.mjs\"\n\t\t\t},\n\t\t\t\"require\": {\n\t\t\t\t\"types\": \"./dist/cjs/api/index.d.cts\",\n\t\t\t\t\"default\": \"./dist/cjs/api/index.cjs\"\n\t\t\t}\n\t\t},\n\t\t\"./esm\": \"./dist/esm/index.mjs\",\n\t\t\"./esm/api\": {\n\t\t\t\"import\": {\n\t\t\t\t\"types\": \"./dist/esm/api/index.d.mts\",\n\t\t\t\t\"default\": \"./dist/esm/api/index.mjs\"\n\t\t\t},\n\t\t\t\"require\": {\n\t\t\t\t\"types\": \"./dist/esm/api/index.d.cts\",\n\t\t\t\t\"default\": \"./dist/esm/api/index.cjs\"\n\t\t\t}\n\t\t},\n\t\t\"./cli\": \"./dist/cli.mjs\",\n\t\t\"./suppress-warnings\": \"./dist/suppress-warnings.cjs\",\n\t\t\"./preflight\": \"./dist/preflight.cjs\",\n\t\t\"./repl\": \"./dist/repl.mjs\"\n\t},\n\t\"packageManager\": \"pnpm@10.9.0\",\n\t\"homepage\": \"https://tsx.is\",\n\t\"scripts\": {\n\t\t\"build\": \"pkgroll --minify\",\n\t\t\"lint\": \"lintroll --node --cache --ignore-pattern 'docs/*.md' .\",\n\t\t\"type-check\": \"tsc\",\n\t\t\"test\": \"pnpm build && node ./dist/cli.mjs tests/index.ts\",\n\t\t\"prepack\": \"pnpm build && clean-pkg-json\",\n\t\t\"docs:dev\": \"pnpm --filter=docs dev\",\n\t\t\"docs:build\": \"pnpm --filter=docs build\",\n\t\t\"docs:preview\": \"pnpm --filter=docs preview\"\n\t},\n\t\"engines\": {\n\t\t\"node\": \">=18.0.0\"\n\t},\n\t\"dependencies\": {\n\t\t\"esbuild\": \"~0.27.0\",\n\t\t\"get-tsconfig\": \"^4.7.5\"\n\t},\n\t\"optionalDependencies\": {\n\t\t\"fsevents\": \"~2.3.3\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@ampproject/remapping\": \"^2.3.0\",\n\t\t\"@types/cross-spawn\": \"^6.0.6\",\n\t\t\"@types/node\": \"^22.15.29\",\n\t\t\"@types/split2\": \"^4.2.3\",\n\t\t\"append-transform\": \"^2.0.0\",\n\t\t\"cachedir\": \"^2.4.0\",\n\t\t\"chokidar\": \"^3.6.0\",\n\t\t\"clean-pkg-json\": \"^1.2.0\",\n\t\t\"cleye\": \"^1.3.2\",\n\t\t\"cross-spawn\": \"^7.0.3\",\n\t\t\"es-module-lexer\": \"^1.5.4\",\n\t\t\"execa\": \"^8.0.1\",\n\t\t\"fs-fixture\": \"^2.4.0\",\n\t\t\"fs-require\": \"^1.6.0\",\n\t\t\"get-node\": \"^15.0.1\",\n\t\t\"kolorist\": \"^1.8.0\",\n\t\t\"lintroll\": \"^1.8.1\",\n\t\t\"magic-string\": \"^0.30.10\",\n\t\t\"manten\": \"^1.5.0\",\n\t\t\"memfs\": \"^4.9.3\",\n\t\t\"outdent\": \"^0.8.0\",\n\t\t\"pkgroll\": \"^2.4.1\",\n\t\t\"proxyquire\": \"^2.1.3\",\n\t\t\"pty-spawn\": \"^1.1.0\",\n\t\t\"strip-ansi\": \"^7.1.0\",\n\t\t\"type-fest\": \"^4.20.1\",\n\t\t\"type-flag\": \"^3.0.0\",\n\t\t\"typescript\": \"^5.5.2\"\n\t},\n\t\"pnpm\": {\n\t\t\"packageExtensions\": {\n\t\t\t\"node-pty\": {\n\t\t\t\t\"//\": \"https://github.com/microsoft/node-pty/issues/777\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"node-gyp\": \"11.0.0\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"onlyBuiltDependencies\": [\n\t\t\t\"node-pty\",\n\t\t\t\"esbuild\"\n\t\t]\n\t}\n}\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - docs\n"
  },
  {
    "path": "release.config.cjs",
    "content": "const outdent = require('outdent');\n\nmodule.exports = {\n\taddReleases: 'bottom',\n\tsuccessComment: outdent`\n\tThis issue is now resolved in [v\\${nextRelease.version}](https://github.com/privatenumber/tsx/releases/tag/v\\${nextRelease.version}).\n\t\n\tIf you're able to, [your sponsorship](https://github.com/sponsors/privatenumber) would be very much appreciated.\n\t`,\n};\n"
  },
  {
    "path": "src/@types/es-module-lexer.d.ts",
    "content": "declare module 'es-module-lexer/js' {\n\texport { parse } from 'es-module-lexer';\n}\n"
  },
  {
    "path": "src/@types/module.d.ts",
    "content": "import 'node:module';\n\ndeclare global {\n\tnamespace NodeJS {\n\t\texport interface Module {\n\t\t\t_compile(code: string, filename: string): string;\n\t\t}\n\t}\n}\n\ndeclare module 'module' {\n\t// CommonJS\n\texport const _extensions: NodeJS.RequireExtensions;\n\n\texport const _cache: NodeJS.Require['cache'];\n\n\texport type Parent = {\n\t\tid: string;\n\n\t\t/**\n\t\t * Can be null if the parent id is 'internal/preload' (e.g. via --require)\n\t\t * which doesn't have a file path.\n\t\t */\n\t\tfilename: string | null;\n\t\tpath: string;\n\t\tpaths: string[];\n\t};\n\n\texport function _resolveFilename(\n\t\trequest: string,\n\t\tparent: Parent | undefined,\n\t\tisMain?: boolean,\n\t\toptions?: Record<PropertyKey, unknown>,\n\t): string;\n\n\texport function _nodeModulePaths(path: string): string[];\n\n\tinterface LoadFnOutput {\n\t\t// Added in https://github.com/nodejs/node/pull/43164\n\t\tresponseURL?: string;\n\t}\n}\n"
  },
  {
    "path": "src/cjs/api/index.ts",
    "content": "export { register } from './register.js';\nexport { require } from './require.js';\n"
  },
  {
    "path": "src/cjs/api/module-extensions.ts",
    "content": "import fs from 'node:fs';\nimport path from 'node:path';\nimport Module from 'node:module';\nimport type { TransformOptions } from 'esbuild';\nimport { transformSync } from '../../utils/transform/index.js';\nimport { transformDynamicImport } from '../../utils/transform/transform-dynamic-import.js';\nimport { isESM } from '../../utils/es-module-lexer.js';\nimport { shouldApplySourceMap, inlineSourceMap } from '../../source-map.js';\nimport { parent } from '../../utils/ipc/client.js';\nimport { fileMatcher } from '../../utils/tsconfig.js';\nimport { logCjs as log } from '../../utils/debug.js';\nimport type { LoaderState } from './types.js';\n\nconst typescriptExtensions = [\n\t'.cts',\n\t'.mts',\n\t'.ts',\n\t'.tsx',\n\t'.jsx',\n] as const;\n\nconst transformExtensions = [\n\t'.js',\n\t'.cjs',\n\t'.mjs',\n] as const;\n\nconst implicitlyResolvableExtensions = [\n\t'.ts',\n\t'.tsx',\n\t'.jsx',\n] as const;\n\nconst safeSet = <T extends Record<string, unknown>>(\n\tobject: T,\n\tproperty: keyof T,\n\tvalue: T[keyof T],\n\tdescriptor?: {\n\t\tenumerable?: boolean;\n\t\tconfigurable?: boolean;\n\t\twritable?: boolean;\n\t},\n) => {\n\tconst existingDescriptor = Object.getOwnPropertyDescriptor(object, property);\n\n\t// If setter is provided, use it\n\tif (existingDescriptor?.set) {\n\t\tobject[property] = value;\n\t} else if (\n\t\t!existingDescriptor\n\t\t|| existingDescriptor.configurable\n\t) {\n\t\tObject.defineProperty(object, property, {\n\t\t\tvalue,\n\t\t\tenumerable: existingDescriptor?.enumerable || descriptor?.enumerable,\n\t\t\twritable: (\n\t\t\t\tdescriptor?.writable\n\t\t\t\t?? (\n\t\t\t\t\texistingDescriptor\n\t\t\t\t\t\t? existingDescriptor.writable\n\t\t\t\t\t\t: true\n\t\t\t\t)\n\t\t\t),\n\t\t\tconfigurable: (\n\t\t\t\tdescriptor?.configurable\n\t\t\t\t?? (\n\t\t\t\t\texistingDescriptor\n\t\t\t\t\t\t? existingDescriptor.configurable\n\t\t\t\t\t\t: true\n\t\t\t\t)\n\t\t\t),\n\t\t});\n\t}\n};\n\nexport const createExtensions = (\n\tstate: LoaderState,\n\textensions: NodeJS.RequireExtensions,\n\tnamespace?: string,\n) => {\n\tconst defaultLoader = extensions['.js'];\n\n\tconst transformer = (\n\t\tmodule: Module,\n\t\tfilePath: string,\n\t) => {\n\t\tif (state.enabled === false) {\n\t\t\treturn defaultLoader(module, filePath);\n\t\t}\n\n\t\t// Make sure __filename doesnt contain query\n\t\tconst [cleanFilePath, query] = filePath.split('?');\n\n\t\tconst searchParams = new URLSearchParams(query);\n\n\t\t// If request namespace doesnt match the namespace, ignore\n\t\tif ((searchParams.get('namespace') ?? undefined) !== namespace) {\n\t\t\treturn defaultLoader(module, filePath);\n\t\t}\n\n\t\tlog(2, 'load', {\n\t\t\tfilePath,\n\t\t});\n\n\t\t/**\n\t\t * In new Module(), m.path = path.dirname(module.id) but module.id coming from\n\t\t * ESM resolver may be a data: path\n\t\t *\n\t\t * In these cases, we fix m.path to be the actual directory of the file\n\t\t */\n\t\t// https://github.com/nodejs/node/blob/v22.8.0/lib/internal/modules/cjs/loader.js#L298\n\t\tif (module.id.startsWith('data:text/javascript,')) {\n\t\t\tmodule.path = path.dirname(cleanFilePath);\n\t\t}\n\n\t\t// For tracking dependencies in watch mode\n\t\tif (parent?.send) {\n\t\t\tparent.send({\n\t\t\t\ttype: 'dependency',\n\t\t\t\tpath: cleanFilePath,\n\t\t\t});\n\t\t}\n\n\t\tconst transformTs = typescriptExtensions.some(extension => cleanFilePath.endsWith(extension));\n\t\tconst transformJs = transformExtensions.some(extension => cleanFilePath.endsWith(extension));\n\t\tif (!transformTs && !transformJs) {\n\t\t\treturn defaultLoader(module, cleanFilePath);\n\t\t}\n\n\t\tlet code = fs.readFileSync(cleanFilePath, 'utf8');\n\n\t\tif (cleanFilePath.endsWith('.cjs')) {\n\t\t\t// Contains native ESM check\n\t\t\tconst transformed = transformDynamicImport(filePath, code);\n\t\t\tif (transformed) {\n\t\t\t\tcode = (\n\t\t\t\t\tshouldApplySourceMap()\n\t\t\t\t\t\t? inlineSourceMap(transformed)\n\t\t\t\t\t\t: transformed.code\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (\n\t\t\ttransformTs\n\n\t\t\t// CommonJS file but uses ESM import/export\n\t\t\t|| isESM(code)\n\t\t) {\n\t\t\tconst transformed = transformSync(\n\t\t\t\tcode,\n\t\t\t\tfilePath,\n\t\t\t\t{\n\t\t\t\t\ttsconfigRaw: fileMatcher?.(cleanFilePath) as TransformOptions['tsconfigRaw'],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tcode = (\n\t\t\t\tshouldApplySourceMap()\n\t\t\t\t\t? inlineSourceMap(transformed)\n\t\t\t\t\t: transformed.code\n\t\t\t);\n\t\t}\n\n\t\tlog(1, 'loaded', {\n\t\t\tfilePath: cleanFilePath,\n\t\t});\n\n\t\tmodule._compile(code, cleanFilePath);\n\t};\n\n\t/**\n\t * Handles .cjs, .cts, .mts & any explicitly specified extension that doesn't match any loaders\n\t *\n\t * Any file requested with an explicit extension will be loaded using the .js loader:\n\t * https://github.com/nodejs/node/blob/e339e9c5d71b72fd09e6abd38b10678e0c592ae7/lib/internal/modules/cjs/loader.js#L430\n\t */\n\tsafeSet(extensions, '.js', transformer);\n\n\tfor (const extension of implicitlyResolvableExtensions) {\n\t\tsafeSet(extensions, extension, transformer, {\n\t\t\t/**\n\t\t\t * Registration needs to be enumerable for some 3rd party libraries\n\t\t\t * https://github.com/gulpjs/rechoir/blob/v0.8.0/index.js#L21 (used by Webpack CLI)\n\t\t\t *\n\t\t\t * If the extension already exists, inherit its enumerable property\n\t\t\t * If not, only expose if it's not namespaced\n\t\t\t */\n\t\t\tenumerable: !namespace,\n\t\t\twritable: true,\n\t\t\tconfigurable: true,\n\t\t});\n\t}\n\n\t/**\n\t * Loaders for extensions .cjs, .cts, & .mts don't need to be\n\t * registered because they're explicitly specified. And unknown\n\t * extensions (incl .cjs) fallsback to using the '.js' loader:\n\t * https://github.com/nodejs/node/blob/v18.4.0/lib/internal/modules/cjs/loader.js#L430\n\t *\n\t * That said, it's actually \".js\" and \".mjs\" that get special treatment\n\t * rather than \".cjs\" (it might as well be \".random-ext\")\n\t */\n\tsafeSet(extensions, '.mjs', transformer, {\n\t\t/**\n\t\t * enumerable defaults to whatever is already set, but if not set, it's false\n\t\t *\n\t\t * This prevent Object.keys from detecting these extensions\n\t\t * when CJS loader iterates over the possible extensions\n\t\t * https://github.com/nodejs/node/blob/v22.2.0/lib/internal/modules/cjs/loader.js#L609\n\t\t */\n\t\twritable: true,\n\t\tconfigurable: true,\n\t});\n\n\t// Unregister\n\treturn () => {\n\t\t/**\n\t\t * The extensions are only reverted if they're still tsx's transformers\n\t\t *\n\t\t * Otherwise, it means they have been wrapped by another loader and should\n\t\t * be left untouched not to remove the other loader\n\t\t */\n\t\tif (extensions['.js'] === transformer) {\n\t\t\textensions['.js'] = defaultLoader;\n\t\t}\n\n\t\tfor (const extension of [...implicitlyResolvableExtensions, '.mjs']) {\n\t\t\tif (extensions[extension] === transformer) {\n\t\t\t\tdelete extensions[extension];\n\t\t\t}\n\t\t}\n\t};\n};\n"
  },
  {
    "path": "src/cjs/api/module-resolve-filename/index.ts",
    "content": "import Module from 'node:module';\nimport { fileURLToPath } from 'node:url';\nimport {\n\tisFilePath,\n\tfileUrlPrefix,\n\ttsExtensionsPattern,\n\tnodeModulesPath,\n} from '../../../utils/path-utils.js';\nimport { tsconfigPathsMatcher } from '../../../utils/tsconfig.js';\nimport type { ResolveFilename, SimpleResolve, LoaderState } from '../types.js';\nimport { logCjs as log } from '../../../utils/debug.js';\nimport { createImplicitResolver } from './resolve-implicit-extensions.js';\nimport { interopCjsExports } from './interop-cjs-exports.js';\nimport { createTsExtensionResolver } from './resolve-ts-extensions.js';\nimport { preserveQuery } from './preserve-query.js';\n\nconst resolveTsPaths = (\n\trequest: string,\n\tparent: Module.Parent | undefined,\n\tnextResolve: SimpleResolve,\n) => {\n\t// Support file protocol\n\tif (request.startsWith(fileUrlPrefix)) {\n\t\trequest = fileURLToPath(request);\n\t}\n\n\t// Resolve TS path alias\n\tif (\n\t\ttsconfigPathsMatcher\n\n\t\t// bare specifier\n\t\t&& !isFilePath(request)\n\n\t\t// Dependency paths should not be resolved using tsconfig.json\n\t\t&& !parent?.filename?.includes(nodeModulesPath)\n\t) {\n\t\tconst possiblePaths = tsconfigPathsMatcher(request);\n\t\tfor (const possiblePath of possiblePaths) {\n\t\t\ttry {\n\t\t\t\treturn nextResolve(possiblePath);\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\treturn nextResolve(request);\n};\n\nexport const createResolveFilename = (\n\tstate: LoaderState,\n\tnextResolve: ResolveFilename,\n\tnamespace?: string,\n): ResolveFilename => (\n\trequest,\n\tparent,\n\t...restOfArgs\n) => {\n\tif (state.enabled === false) {\n\t\treturn nextResolve(request, parent, ...restOfArgs);\n\t}\n\n\trequest = interopCjsExports(request);\n\n\tconst [\n\t\tcleanRequest,\n\t\tsearchParams,\n\t\tappendQuery,\n\t] = preserveQuery(request, parent);\n\n\t// If request namespace doesnt match the namespace, ignore\n\tif ((searchParams.get('namespace') ?? undefined) !== namespace) {\n\t\treturn nextResolve(request, parent, ...restOfArgs);\n\t}\n\n\tlog(2, 'resolve', {\n\t\trequest,\n\t\tparent: parent?.filename ?? parent,\n\t\trestOfArgs,\n\t});\n\n\tlet nextResolveSimple: SimpleResolve = request_ => nextResolve(\n\t\trequest_,\n\t\tparent,\n\t\t...restOfArgs,\n\t);\n\n\tnextResolveSimple = createTsExtensionResolver(\n\t\tnextResolveSimple,\n\t\tBoolean(\n\t\t\t// If register.namespace is used (e.g. tsx.require())\n\t\t\tnamespace\n\n\t\t\t// If parent is a TS file\n\t\t\t|| (parent?.filename && tsExtensionsPattern.test(parent.filename)),\n\t\t),\n\t);\n\n\tnextResolveSimple = createImplicitResolver(nextResolveSimple);\n\n\tconst resolved = appendQuery(\n\t\tresolveTsPaths(cleanRequest, parent, nextResolveSimple),\n\t\trestOfArgs.length,\n\t);\n\n\tlog(1, 'resolved', {\n\t\trequest,\n\t\tparent: parent?.filename ?? parent,\n\t\tresolved,\n\t});\n\n\treturn resolved;\n};\n"
  },
  {
    "path": "src/cjs/api/module-resolve-filename/interop-cjs-exports.ts",
    "content": "import Module from 'node:module';\n\nexport const getOriginalFilePath = (\n\trequest: string,\n) => {\n\tif (!request.startsWith('data:text/javascript,')) {\n\t\treturn;\n\t}\n\n\tconst queryIndex = request.indexOf('?');\n\tif (queryIndex === -1) {\n\t\treturn;\n\t}\n\n\tconst searchParams = new URLSearchParams(request.slice(queryIndex + 1));\n\tconst filePath = searchParams.get('filePath');\n\tif (filePath) {\n\t\treturn filePath;\n\t}\n};\n\nexport const interopCjsExports = (\n\trequest: string,\n) => {\n\tconst filePath = getOriginalFilePath(request);\n\tif (filePath) {\n\t\t// The CJS module cache needs to be updated with the actual path for export parsing to work\n\t\t// https://github.com/nodejs/node/blob/v22.2.0/lib/internal/modules/esm/translators.js#L338\n\t\tModule._cache[filePath] = Module._cache[request];\n\t\tdelete Module._cache[request];\n\t\trequest = filePath;\n\t}\n\treturn request;\n};\n"
  },
  {
    "path": "src/cjs/api/module-resolve-filename/is-from-cjs-lexer.ts",
    "content": "const cjsPreparseCall = 'at cjsPreparseModuleExports (node:internal';\n\nexport const isFromCjsLexer = (\n\terror: Error,\n) => {\n\tconst stack = error.stack!.split('\\n').slice(1);\n\treturn (\n\t\tstack[1].includes(cjsPreparseCall)\n\t\t|| stack[2].includes(cjsPreparseCall)\n\t);\n};\n"
  },
  {
    "path": "src/cjs/api/module-resolve-filename/preserve-query.ts",
    "content": "import path from 'node:path';\nimport Module from 'node:module';\nimport { urlSearchParamsStringify } from '../../../utils/url-search-params-stringify.js';\nimport { isFromCjsLexer } from './is-from-cjs-lexer.js';\nimport { getOriginalFilePath } from './interop-cjs-exports.js';\n\nexport const preserveQuery = (\n\trequest: string,\n\tparent?: Module.Parent,\n) => {\n\t// Strip query string\n\tconst requestAndQuery = request.split('?');\n\tconst searchParams = new URLSearchParams(requestAndQuery[1]);\n\n\tif (parent?.filename) {\n\t\tconst filePath = getOriginalFilePath(parent.filename);\n\t\tlet query: string | undefined;\n\t\tif (filePath) {\n\t\t\tconst pathAndQuery = filePath.split('?');\n\t\t\tconst newFilename = pathAndQuery[0];\n\t\t\tquery = pathAndQuery[1];\n\n\t\t\t/**\n\t\t\t * Can't delete the old cache entry because there's an assertion\n\t\t\t * https://github.com/nodejs/node/blob/v20.15.0/lib/internal/modules/esm/translators.js#L347\n\t\t\t */\n\t\t\t// delete Module._cache[parent.filename];\n\n\t\t\tparent.filename = newFilename;\n\t\t\tparent.path = path.dirname(newFilename);\n\t\t\t// https://github.com/nodejs/node/blob/v20.15.0/lib/internal/modules/esm/translators.js#L383\n\t\t\tparent.paths = Module._nodeModulePaths(parent.path);\n\n\t\t\tModule._cache[newFilename] = parent as NodeModule;\n\t\t}\n\n\t\tif (!query) {\n\t\t\tquery = parent.filename.split('?')[1];\n\t\t}\n\n\t\t// Inherit parent namespace if it exists\n\t\tconst parentQuery = new URLSearchParams(query);\n\t\tconst parentNamespace = parentQuery.get('namespace');\n\t\tif (parentNamespace) {\n\t\t\tsearchParams.append('namespace', parentNamespace);\n\t\t}\n\t}\n\n\treturn [\n\t\trequestAndQuery[0],\n\t\tsearchParams,\n\t\t(\n\t\t\tresolved: string,\n\t\t\trestOfArgsLength: number,\n\t\t) => {\n\t\t\t// Only add query back if it's a file path (not a core Node module)\n\t\t\tif (\n\t\t\t\tpath.isAbsolute(resolved)\n\n\t\t\t\t// These two have native loaders which don't support queries\n\t\t\t\t&& !resolved.endsWith('.json')\n\t\t\t\t&& !resolved.endsWith('.node')\n\n\t\t\t\t/**\n\t\t\t\t * Detect if this is called by the CJS lexer, the resolved path is directly passed into\n\t\t\t\t * readFile to parse the exports\n\t\t\t\t */\n\t\t\t\t&& !(\n\t\t\t\t\t// Only the CJS lexer doesn't pass in the rest of the arguments\n\t\t\t\t\t// https://github.com/nodejs/node/blob/v20.15.0/lib/internal/modules/esm/translators.js#L415\n\t\t\t\t\trestOfArgsLength === 0\n\t\t\t\t\t// eslint-disable-next-line unicorn/error-message\n\t\t\t\t\t&& isFromCjsLexer(new Error())\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tresolved += urlSearchParamsStringify(searchParams);\n\t\t\t}\n\n\t\t\treturn resolved;\n\t\t},\n\t] as const;\n};\n"
  },
  {
    "path": "src/cjs/api/module-resolve-filename/resolve-implicit-extensions.ts",
    "content": "import path from 'node:path';\nimport type { NodeError } from '../../../types.js';\nimport { isDirectoryPattern } from '../../../utils/path-utils.js';\nimport type { SimpleResolve } from '../types.js';\n\n/**\n * Custom re-implementation of the CommonJS implicit resolver\n *\n * - Resolves .ts over .js extensions\n * - When namespaced, the loaders are registered to the extensions in a hidden way\n * so Node's built-in implicit resolver will not try those extensions\n */\nexport const createImplicitResolver = (\n\tnextResolve: SimpleResolve,\n): SimpleResolve => (\n\trequest,\n) => {\n\tif (request === '.' || request === '..' || request.endsWith('/..')) {\n\t\trequest += '/';\n\t}\n\n\t/**\n\t * Currently, there's an edge case where it doesn't resolve index.ts over index.js\n\t * if the request doesn't end with a slash. e.g. `import './dir'`\n\t * Doesn't handle '.' either\n\t */\n\tif (isDirectoryPattern.test(request)) {\n\t\t// If directory, can be index.js, index.ts, etc.\n\t\tlet joinedPath = path.join(request, 'index.js');\n\n\t\t/**\n\t\t * path.join will remove the './' prefix if it exists\n\t\t * but it should only be added back if it was there before\n\t\t * (e.g. not package directory imports)\n\t\t */\n\t\tif (request.startsWith('./')) {\n\t\t\tjoinedPath = `./${joinedPath}`;\n\t\t}\n\n\t\ttry {\n\t\t\treturn nextResolve(joinedPath);\n\t\t} catch {}\n\t}\n\n\ttry {\n\t\treturn nextResolve(request);\n\t} catch (_error) {\n\t\tconst nodeError = _error as NodeError;\n\n\t\tif (nodeError.code === 'MODULE_NOT_FOUND') {\n\t\t\ttry {\n\t\t\t\treturn nextResolve(`${request}${path.sep}index.js`);\n\t\t\t} catch {}\n\t\t}\n\n\t\tthrow nodeError;\n\t}\n};\n"
  },
  {
    "path": "src/cjs/api/module-resolve-filename/resolve-ts-extensions.ts",
    "content": "import { mapTsExtensions } from '../../../utils/map-ts-extensions.js';\nimport type { NodeError } from '../../../types.js';\nimport {\n\tisFilePath,\n\tisDirectoryPattern,\n} from '../../../utils/path-utils.js';\nimport { allowJs } from '../../../utils/tsconfig.js';\nimport type { SimpleResolve } from '../types.js';\nimport { logCjs as log } from '../../../utils/debug.js';\n\n/**\n * Typescript gives .ts, .cts, or .mts priority over actual .js, .cjs, or .mjs extensions\n */\nconst resolveTsFilename = (\n\tresolve: SimpleResolve,\n\trequest: string,\n\tisTsParent: boolean,\n) => {\n\tlog(3, 'resolveTsFilename', {\n\t\trequest,\n\t\tisDirectory: isDirectoryPattern.test(request),\n\t\tisTsParent,\n\t\tallowJs,\n\t});\n\tif (\n\t\tisDirectoryPattern.test(request)\n\t\t|| (!isTsParent && !allowJs)\n\t) {\n\t\treturn;\n\t}\n\n\tconst tsPath = mapTsExtensions(request);\n\tif (!tsPath) {\n\t\treturn;\n\t}\n\n\tfor (const tryTsPath of tsPath) {\n\t\ttry {\n\t\t\treturn resolve(tryTsPath);\n\t\t} catch (error) {\n\t\t\tconst { code } = error as NodeError;\n\t\t\tif (\n\t\t\t\tcode !== 'MODULE_NOT_FOUND'\n\t\t\t\t&& code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED'\n\t\t\t) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n};\n\nexport const createTsExtensionResolver = (\n\tnextResolve: SimpleResolve,\n\tisTsParent: boolean,\n): SimpleResolve => (\n\trequest,\n) => {\n\tlog(3, 'resolveTsFilename', {\n\t\trequest,\n\t\tisTsParent,\n\t\tisFilePath: isFilePath(request),\n\t});\n\n\t// It should only try to resolve TS extensions first if it's a local file (non dependency)\n\tif (isFilePath(request)) {\n\t\tconst resolvedTsFilename = resolveTsFilename(nextResolve, request, isTsParent);\n\t\tif (resolvedTsFilename) {\n\t\t\treturn resolvedTsFilename;\n\t\t}\n\t}\n\n\ttry {\n\t\treturn nextResolve(request);\n\t} catch (error) {\n\t\tconst nodeError = error as NodeError;\n\n\t\tif (nodeError.code === 'MODULE_NOT_FOUND') {\n\t\t\t// Exports map resolution\n\t\t\tif (nodeError.path) {\n\t\t\t\tconst isExportsPath = nodeError.message.match(/^Cannot find module '([^']+)'$/);\n\t\t\t\tif (isExportsPath) {\n\t\t\t\t\tconst exportsPath = isExportsPath[1];\n\t\t\t\t\tconst tsFilename = resolveTsFilename(nextResolve, exportsPath, isTsParent);\n\t\t\t\t\tif (tsFilename) {\n\t\t\t\t\t\treturn tsFilename;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst isMainPath = nodeError.message.match(/^Cannot find module '([^']+)'. Please verify that the package.json has a valid \"main\" entry$/);\n\t\t\t\tif (isMainPath) {\n\t\t\t\t\tconst mainPath = isMainPath[1];\n\t\t\t\t\tconst tsFilename = resolveTsFilename(nextResolve, mainPath, isTsParent);\n\t\t\t\t\tif (tsFilename) {\n\t\t\t\t\t\treturn tsFilename;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst resolvedTsFilename = resolveTsFilename(nextResolve, request, isTsParent);\n\t\t\tif (resolvedTsFilename) {\n\t\t\t\treturn resolvedTsFilename;\n\t\t\t}\n\t\t}\n\n\t\tthrow nodeError;\n\t}\n};\n"
  },
  {
    "path": "src/cjs/api/register.ts",
    "content": "import Module from 'node:module';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { loadTsconfig } from '../../utils/tsconfig.js';\nimport type { RequiredProperty } from '../../types.js';\nimport { urlSearchParamsStringify } from '../../utils/url-search-params-stringify.js';\nimport { fileUrlPrefix } from '../../utils/path-utils.js';\nimport type { LoaderState } from './types.js';\nimport { createExtensions } from './module-extensions.js';\nimport { createResolveFilename } from './module-resolve-filename/index.js';\n\nconst resolveContext = (\n\tid: string,\n\tfromFile: string | URL,\n) => {\n\tif (!fromFile) {\n\t\tthrow new Error('The current file path (__filename or import.meta.url) must be provided in the second argument of tsx.require()');\n\t}\n\n\t// If id is not a relative path, it doesn't need to be resolved\n\tif (!id.startsWith('.')) {\n\t\treturn id;\n\t}\n\n\tif (\n\t\t(typeof fromFile === 'string' && fromFile.startsWith(fileUrlPrefix))\n\t\t|| fromFile instanceof URL\n\t) {\n\t\tfromFile = fileURLToPath(fromFile);\n\t}\n\n\treturn path.resolve(path.dirname(fromFile), id);\n};\n\ntype RegisterOptions = {\n\tnamespace?: string;\n};\n\nexport type Unregister = () => void;\n\ntype ScopedRequire = (\n\tid: string,\n\tfromFile: string | URL,\n) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\ntype ScopedResolve = (\n\tid: string,\n\tfromFile: string | URL,\n\tresolveOptions?: { paths?: string[] | undefined },\n) => string;\n\nexport type NamespacedUnregister = Unregister & {\n\trequire: ScopedRequire;\n\tresolve: ScopedResolve;\n\tunregister: Unregister;\n};\n\nexport type Register = {\n\t(options: RequiredProperty<RegisterOptions, 'namespace'>): NamespacedUnregister;\n\t(options?: RegisterOptions): Unregister;\n};\n\nexport const register: Register = (\n\toptions,\n) => {\n\tconst { sourceMapsEnabled } = process;\n\tconst state: LoaderState = {\n\t\tenabled: true,\n\t};\n\n\tloadTsconfig(process.env.TSX_TSCONFIG_PATH);\n\n\t// register\n\tprocess.setSourceMapsEnabled(true);\n\n\tconst originalResolveFilename = Module._resolveFilename;\n\tconst resolveFilename = createResolveFilename(state, originalResolveFilename, options?.namespace);\n\tModule._resolveFilename = resolveFilename;\n\n\tconst unregisterExtensions = createExtensions(state, Module._extensions, options?.namespace);\n\n\tconst unregister = () => {\n\t\tif (sourceMapsEnabled === false) {\n\t\t\tprocess.setSourceMapsEnabled(false);\n\t\t}\n\t\tstate.enabled = false;\n\n\t\t/**\n\t\t * Only revert the _resolveFilename & extensions if they're unwrapped\n\t\t * by another loader extension\n\t\t */\n\t\tif (Module._resolveFilename === resolveFilename) {\n\t\t\tModule._resolveFilename = originalResolveFilename;\n\t\t}\n\t\tunregisterExtensions();\n\t};\n\n\tif (options?.namespace) {\n\t\tconst scopedRequire: ScopedRequire = (id, fromFile) => {\n\t\t\tconst resolvedId = resolveContext(id, fromFile);\n\t\t\tconst [request, query] = resolvedId.split('?');\n\n\t\t\tconst parameters = new URLSearchParams(query);\n\t\t\tif (options.namespace && !request.startsWith('node:')) {\n\t\t\t\tparameters.set('namespace', options.namespace);\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports, import-x/no-dynamic-require\n\t\t\treturn require(request + urlSearchParamsStringify(parameters));\n\t\t};\n\t\tunregister.require = scopedRequire;\n\n\t\tconst scopedResolve: ScopedResolve = (id, fromFile, resolveOptions) => {\n\t\t\tconst resolvedId = resolveContext(id, fromFile);\n\t\t\tconst [request, query] = resolvedId.split('?');\n\n\t\t\tconst parameters = new URLSearchParams(query);\n\t\t\tif (options.namespace && !request.startsWith('node:')) {\n\t\t\t\tparameters.set('namespace', options.namespace);\n\t\t\t}\n\n\t\t\treturn resolveFilename(\n\t\t\t\trequest + urlSearchParamsStringify(parameters),\n\t\t\t\tmodule,\n\t\t\t\tfalse,\n\t\t\t\tresolveOptions,\n\t\t\t);\n\t\t};\n\t\tunregister.resolve = scopedResolve;\n\t\tunregister.unregister = unregister;\n\t}\n\n\treturn unregister;\n};\n"
  },
  {
    "path": "src/cjs/api/require.ts",
    "content": "import { register, type NamespacedUnregister } from './register.js';\n\nlet api: NamespacedUnregister | undefined;\nconst tsxRequire = (\n\tid: string,\n\tfromFile: string | URL,\n) => {\n\tif (!api) {\n\t\tapi = register({\n\t\t\tnamespace: Date.now().toString(),\n\t\t});\n\t}\n\treturn api.require(id, fromFile);\n};\n\nconst resolve = (\n\tid: string,\n\tfromFile: string | URL,\n\toptions?: { paths?: string[] | undefined },\n) => {\n\tif (!api) {\n\t\tapi = register({\n\t\t\tnamespace: Date.now().toString(),\n\t\t});\n\t}\n\treturn api.resolve(id, fromFile, options);\n};\nresolve.paths = require.resolve.paths;\n\ntsxRequire.resolve = resolve;\ntsxRequire.main = require.main;\ntsxRequire.extensions = require.extensions;\ntsxRequire.cache = require.cache;\n\nexport { tsxRequire as require };\n"
  },
  {
    "path": "src/cjs/api/types.ts",
    "content": "import type Module from 'node:module';\n\nexport type LoaderState = {\n\tenabled: boolean;\n};\n\nexport type ResolveFilename = typeof Module._resolveFilename;\n\nexport type SimpleResolve = (request: string) => string;\n"
  },
  {
    "path": "src/cjs/index.ts",
    "content": "import { register } from './api/register.js';\n\nregister();\n"
  },
  {
    "path": "src/cli.ts",
    "content": "import { constants as osConstants } from 'node:os';\nimport type { ChildProcess, Serializable } from 'node:child_process';\nimport type { Server } from 'node:net';\nimport { cli } from 'cleye';\nimport {\n\ttransformSync as esbuildTransformSync,\n} from 'esbuild';\nimport { version } from '../package.json';\nimport { run } from './run.js';\nimport { watchCommand } from './watch/index.js';\nimport {\n\tremoveArgvFlags,\n\tignoreAfterArgument,\n} from './remove-argv-flags.js';\nimport { isFeatureSupported, testRunnerGlob } from './utils/node-features.js';\nimport { createIpcServer } from './utils/ipc/server.js';\n\n// const debug = (...messages: any[]) => {\n// \tif (process.env.DEBUG) {\n// \t\tconsole.log(...messages);\n// \t}\n// };\n\nconst relaySignals = (\n\tchildProcess: ChildProcess,\n\tipcSocket: Server,\n) => {\n\tlet waitForSignal: undefined | ((signal: NodeJS.Signals) => void);\n\n\tipcSocket.on(\n\t\t'data',\n\t\t(\n\t\t\tdata: {\n\t\t\t\ttype: string;\n\t\t\t\tsignal: NodeJS.Signals;\n\t\t\t},\n\t\t) => {\n\t\t\tif (\n\t\t\t\tdata\n\t\t\t\t&& data.type === 'signal'\n\t\t\t\t&& waitForSignal\n\t\t\t) {\n\t\t\t\twaitForSignal(data.signal);\n\t\t\t}\n\t\t},\n\t);\n\n\t/**\n\t * Wait for signal from preflight bindHiddenSignalsHandler\n\t * Ideally the timeout should be as low as possible\n\t * since the child lets the parent know that it received\n\t * the signal\n\t */\n\tconst waitForSignalFromChild = () => {\n\t\tconst p = new Promise<NodeJS.Signals | undefined>((resolve) => {\n\t\t\t// Aribrary timeout based on flaky tests\n\t\t\tsetTimeout(() => resolve(undefined), 30);\n\t\t\twaitForSignal = resolve;\n\t\t});\n\n\t\tp.then(\n\t\t\t() => {\n\t\t\t\twaitForSignal = undefined;\n\t\t\t},\n\t\t\t() => {},\n\t\t);\n\n\t\treturn p;\n\t};\n\n\tconst relaySignalToChild = async (\n\t\tsignal: NodeJS.Signals,\n\t) => {\n\t\t/**\n\t\t * This callback is triggered if the parent receives a signal\n\t\t *\n\t\t * Child could also receive a signal at the same time if it detected\n\t\t * a keypress or was sent a signal via process group\n\t\t *\n\t\t * The preflight registers a signal handler on the child to\n\t\t * tell the parent if it also received a signal which we wait for here\n\t\t */\n\t\tconst signalFromChild = await waitForSignalFromChild();\n\n\t\t// debug({\n\t\t// \tsignalFromChild,\n\t\t// });\n\n\t\t/**\n\t\t * If child didn't receive a signal, it's either because it was\n\t\t * sent to the parent directly via kill PID or the child is\n\t\t * unresponsive (e.g. infinite loop). Relay signal to child.\n\t\t */\n\t\tif (signalFromChild !== signal) {\n\t\t\t// debug('killing child', {\n\t\t\t// \tsignal,\n\t\t\t// });\n\t\t\tchildProcess.kill(signal);\n\n\t\t\t/**\n\t\t\t * If child is unresponsive (e.g. infinite loop), we need to force kill it\n\t\t\t */\n\t\t\tconst isChildResponsive = await waitForSignalFromChild();\n\t\t\tif (isChildResponsive !== signal) {\n\t\t\t\t// This seems to run before the handler registered at the bottom of this file\n\t\t\t\t// Seems the lastest handler is called first\n\t\t\t\tchildProcess.on('exit', () => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Even though this may not be a SIGKILL, I've confirmed Ctrl+C on an infinite looping\n\t\t\t\t\t * file exits with 130, which is 128 + 2 (SIGINT)\n\t\t\t\t\t *\n\t\t\t\t\t * https://nodejs.org/api/process.html#exit-codes\n\t\t\t\t\t * >128 Signal Exits: If Node.js receives a fatal signal such as SIGKILL or SIGHUP,\n\t\t\t\t\t * then its exit code will be 128 plus the value of the signal code. This is a\n\t\t\t\t\t * standard POSIX practice, since exit codes are defined to be 7-bit integers, and\n\t\t\t\t\t * signal exits set the high-order bit, and then contain the value of the signal code.\n\t\t\t\t\t * For example, signal SIGABRT has value 6, so the expected exit code will be 128 + 6,\n\t\t\t\t\t * or 134.\n\t\t\t\t\t */\n\t\t\t\t\tconst exitCode = osConstants.signals[signal];\n\t\t\t\t\tprocess.exit(128 + exitCode);\n\t\t\t\t});\n\n\t\t\t\tchildProcess.kill('SIGKILL');\n\t\t\t}\n\t\t}\n\t};\n\n\tprocess.on('SIGINT', relaySignalToChild);\n\tprocess.on('SIGTERM', relaySignalToChild);\n};\n\nconst tsxFlags = {\n\tnoCache: {\n\t\ttype: Boolean,\n\t\tdescription: 'Disable caching',\n\t},\n\ttsconfig: {\n\t\ttype: String,\n\t\tdescription: 'Custom tsconfig.json path',\n\t},\n};\n\ncli({\n\tname: 'tsx',\n\tparameters: ['[script path]'],\n\tcommands: [\n\t\twatchCommand,\n\t],\n\tflags: {\n\t\t...tsxFlags,\n\t\tversion: {\n\t\t\ttype: Boolean,\n\t\t\talias: 'v',\n\t\t\tdescription: 'Show version',\n\t\t},\n\t\thelp: {\n\t\t\ttype: Boolean,\n\t\t\talias: 'h',\n\t\t\tdescription: 'Show help',\n\t\t},\n\t},\n\thelp: false,\n\tignoreArgv: ignoreAfterArgument(),\n}, async (argv) => {\n\tif (argv.flags.version) {\n\t\tprocess.stdout.write(`tsx v${version}\\nnode `);\n\t} else if (argv.flags.help) {\n\t\targv.showHelp({\n\t\t\tdescription: 'Node.js runtime enhanced with esbuild for loading TypeScript & ESM',\n\t\t});\n\t\tconsole.log(`${'-'.repeat(45)}\\n`);\n\t}\n\n\tconst interceptFlags = {\n\t\teval: {\n\t\t\ttype: String,\n\t\t\talias: 'e',\n\t\t},\n\t\tprint: {\n\t\t\ttype: String,\n\t\t\talias: 'p',\n\t\t},\n\t} as const;\n\n\tconst {\n\t\t_: firstArgs,\n\t\tflags: interceptedFlags,\n\t} = cli({\n\t\tflags: {\n\t\t\t...interceptFlags,\n\t\t\tinputType: String,\n\t\t\ttest: Boolean,\n\t\t},\n\t\thelp: false,\n\t\tignoreArgv: ignoreAfterArgument(false),\n\t});\n\n\tconst argvsToRun = removeArgvFlags({\n\t\t...tsxFlags,\n\t\t...interceptFlags,\n\t});\n\n\tconst evalTypes = ['print', 'eval'] as const;\n\tconst evalType = evalTypes.find(type => Boolean(interceptedFlags[type]));\n\tif (evalType) {\n\t\tconst { inputType } = interceptedFlags;\n\t\tconst evalCode = interceptedFlags[evalType]!;\n\t\tconst transformed = esbuildTransformSync(\n\t\t\tevalCode,\n\t\t\t{\n\t\t\t\tloader: 'default',\n\t\t\t\tsourcefile: '/eval.ts',\n\t\t\t\tformat: inputType === 'module' ? 'esm' : 'cjs',\n\t\t\t},\n\t\t);\n\n\t\targvsToRun.unshift(`--${evalType}`, transformed.code);\n\t}\n\n\t// Default --test glob to find TypeScript files\n\tif (\n\t\tisFeatureSupported(testRunnerGlob)\n\t\t&& interceptedFlags.test\n\t\t&& firstArgs.length === 0\n\t) {\n\t\targvsToRun.push('**/{test,test/**/*,test-*,*[.-_]test}.?(c|m)@(t|j)s');\n\t}\n\n\tconst ipc = await createIpcServer();\n\n\tconst childProcess = run(\n\t\targvsToRun,\n\t\t{\n\t\t\tnoCache: Boolean(argv.flags.noCache),\n\t\t\ttsconfigPath: argv.flags.tsconfig,\n\t\t},\n\t);\n\n\trelaySignals(childProcess, ipc);\n\n\tif (process.send) {\n\t\tchildProcess.on('message', (message) => {\n\t\t\tprocess.send!(message);\n\t\t});\n\t}\n\n\tif (childProcess.send) {\n\t\tprocess.on('message', (message) => {\n\t\t\tchildProcess.send(message as Serializable);\n\t\t});\n\t}\n\n\tchildProcess.on(\n\t\t'close',\n\t\t(exitCode) => {\n\t\t\t// If there's no exit code, it's likely killed by a signal\n\t\t\t// https://nodejs.org/api/process.html#process_exit_codes\n\t\t\tif (exitCode === null) {\n\t\t\t\texitCode = osConstants.signals[childProcess.signalCode!] + 128;\n\t\t\t}\n\t\t\tprocess.exit(exitCode);\n\t\t},\n\t);\n});\n"
  },
  {
    "path": "src/esm/api/index.ts",
    "content": "export {\n\tregister,\n\ttype InitializationOptions,\n\ttype NamespacedUnregister,\n\ttype Register,\n\ttype RegisterOptions,\n\ttype Unregister,\n} from './register.js';\nexport type { ScopedImport } from './scoped-import.js';\nexport { tsImport } from './ts-import.js';\n"
  },
  {
    "path": "src/esm/api/register.ts",
    "content": "import module from 'node:module';\nimport { MessageChannel, type MessagePort } from 'node:worker_threads';\nimport type { Message } from '../types.js';\nimport type { RequiredProperty } from '../../types.js';\nimport { interopCjsExports } from '../../cjs/api/module-resolve-filename/interop-cjs-exports.js';\nimport { createScopedImport, type ScopedImport } from './scoped-import.js';\n\nexport type TsconfigOptions = false | string;\n\nexport type InitializationOptions = {\n\tnamespace?: string;\n\tport?: MessagePort;\n\ttsconfig?: TsconfigOptions;\n};\n\nexport type RegisterOptions = {\n\tnamespace?: string;\n\tonImport?: (url: string) => void;\n\ttsconfig?: TsconfigOptions;\n};\n\nexport type Unregister = () => Promise<void>;\n\nexport type NamespacedUnregister = Unregister & {\n\timport: ScopedImport;\n\tunregister: Unregister;\n};\n\nexport type Register = {\n\t(options: RequiredProperty<RegisterOptions, 'namespace'>): NamespacedUnregister;\n\t(options?: RegisterOptions): Unregister;\n};\n\nlet cjsInteropApplied = false;\n\nexport const register: Register = (\n\toptions,\n) => {\n\tif (!module.register) {\n\t\tthrow new Error(`This version of Node.js (${process.version}) does not support module.register(). Please upgrade to Node v18.19 or v20.6 and above.`);\n\t}\n\n\tif (!cjsInteropApplied) {\n\t\tconst { _resolveFilename } = module;\n\t\tmodule._resolveFilename = (\n\t\t\trequest,\n\t\t\t...restOfArgs\n\t\t) => _resolveFilename(\n\t\t\tinteropCjsExports(request),\n\t\t\t...restOfArgs,\n\t\t);\n\t\tcjsInteropApplied = true;\n\t}\n\n\tconst { sourceMapsEnabled } = process;\n\tprocess.setSourceMapsEnabled(true);\n\n\tconst { port1, port2 } = new MessageChannel();\n\tmodule.register(\n\t\t// Load new copy of loader so it can be registered multiple times\n\t\t`./esm/index.mjs?${Date.now()}`,\n\t\t{\n\t\t\tparentURL: import.meta.url,\n\t\t\tdata: {\n\t\t\t\tport: port2,\n\t\t\t\tnamespace: options?.namespace,\n\t\t\t\ttsconfig: options?.tsconfig,\n\t\t\t} satisfies InitializationOptions,\n\t\t\ttransferList: [port2],\n\t\t},\n\t);\n\n\tconst onImport = options?.onImport;\n\tconst importHandler = onImport && ((message: Message) => {\n\t\tif (message.type === 'load') {\n\t\t\tonImport(message.url);\n\t\t}\n\t});\n\n\tif (importHandler) {\n\t\tport1.on('message', importHandler);\n\t\tport1.unref();\n\t}\n\n\t// unregister\n\tconst unregister = () => {\n\t\tif (sourceMapsEnabled === false) {\n\t\t\tprocess.setSourceMapsEnabled(false);\n\t\t}\n\n\t\tif (importHandler) {\n\t\t\tport1.off('message', importHandler);\n\t\t}\n\n\t\tport1.postMessage('deactivate');\n\n\t\t// Not necessary to wait, but provide the option\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tconst onDeactivated = (message: Message) => {\n\t\t\t\tif (message.type === 'deactivated') {\n\t\t\t\t\tresolve();\n\t\t\t\t\tport1.off('message', onDeactivated);\n\t\t\t\t}\n\t\t\t};\n\t\t\tport1.on('message', onDeactivated);\n\t\t});\n\t};\n\n\tif (options?.namespace) {\n\t\tunregister.import = createScopedImport(options.namespace);\n\t\tunregister.unregister = unregister;\n\t}\n\n\treturn unregister;\n};\n"
  },
  {
    "path": "src/esm/api/scoped-import.ts",
    "content": "import { pathToFileURL } from 'node:url';\nimport type { TsxRequest } from '../types.js';\nimport { fileUrlPrefix } from '../../utils/path-utils.js';\n\nexport type ScopedImport = (\n\tspecifier: string,\n\tparent: string,\n) => Promise<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n\nexport const createScopedImport = (\n\tnamespace: string,\n): ScopedImport => (\n\tspecifier,\n\tparent,\n) => {\n\tif (!parent) {\n\t\tthrow new Error('The current file path (import.meta.url) must be provided in the second argument of tsImport()');\n\t}\n\n\tconst parentURL = (\n\t\tparent.startsWith(fileUrlPrefix)\n\t\t\t? parent\n\t\t\t: pathToFileURL(parent).toString()\n\t);\n\n\treturn import(\n\t\t`tsx://${JSON.stringify({\n\t\t\tspecifier,\n\t\t\tparentURL,\n\t\t\tnamespace,\n\t\t} satisfies TsxRequest)}`\n\t);\n};\n"
  },
  {
    "path": "src/esm/api/ts-import.ts",
    "content": "import { register as cjsRegister } from '../../cjs/api/index.js';\nimport { isFeatureSupported, esmLoadReadFile } from '../../utils/node-features.js';\nimport { isBarePackageNamePattern, cjsExtensionPattern } from '../../utils/path-utils.js';\nimport { register, type TsconfigOptions } from './register.js';\n\ntype Options = {\n\tparentURL: string;\n\tonImport?: (url: string) => void;\n\ttsconfig?: TsconfigOptions;\n};\n\nconst tsImport = (\n\tspecifier: string,\n\toptions: string | Options,\n) => {\n\tif (\n\t\t!options\n\t\t|| (typeof options === 'object' && !options.parentURL)\n\t) {\n\t\tthrow new Error('The current file path (import.meta.url) must be provided in the second argument of tsImport()');\n\t}\n\n\tconst isOptionsString = typeof options === 'string';\n\tconst parentURL = isOptionsString ? options : options.parentURL;\n\tconst namespace = Date.now().toString();\n\n\t// Keep registered for hanging require() calls\n\tconst cjs = cjsRegister({\n\t\tnamespace,\n\t});\n\n\t/**\n\t * In Node v18, the loader doesn't support reading the CommonJS from\n\t * a data URL, so it can't actually relay the namespace. This is a workaround\n\t * to preemptively determine whether the file is a CommonJS file, and shortcut\n\t * to using the CommonJS loader instead of going through the ESM loader first\n\t */\n\tif (\n\t\t!isFeatureSupported(esmLoadReadFile)\n\t\t&& (\n\t\t\t!isBarePackageNamePattern.test(specifier)\n\t\t\t&& cjsExtensionPattern.test(specifier)\n\t\t)\n\t) {\n\t\treturn Promise.resolve(cjs.require(specifier, parentURL));\n\t}\n\n\t/**\n\t * We don't want to unregister this after load since there can be child import() calls\n\t * that need TS support\n\t *\n\t * This is not accessible to others because of the namespace\n\t */\n\tconst api = register({\n\t\tnamespace,\n\t\t...(\n\t\t\tisOptionsString\n\t\t\t\t? {}\n\t\t\t\t: options\n\t\t),\n\t});\n\n\treturn api.import(specifier, parentURL);\n};\n\n/**\n * Considered implmenting import.meta.resolve(), but natively, it doesn't seem to actully\n * resolve relative file paths.\n *\n * For example, this doesn't throw: import.meta.resolve('./missing-file')\n */\n// tsImport.meta = {\n// \tresolve: (\n// \t\tspecifier: string,\n// \t\tfromFile: string,\n// \t) => {\n// \t\tconst resolvedUrl = resolveSpecifier(specifier, fromFile);\n// \t\tconst unregister = register();\n// \t\ttry {\n// \t\t\treturn import.meta.resolve(resolvedUrl);\n// \t\t} finally {\n// \t\t\tunregister();\n// \t\t}\n// \t}\n// };\n\nexport { tsImport };\n"
  },
  {
    "path": "src/esm/hook/index.ts",
    "content": "export { initialize, globalPreload } from './initialize.js';\nexport { load } from './load.js';\nexport { resolve } from './resolve.js';\n"
  },
  {
    "path": "src/esm/hook/initialize.ts",
    "content": "import type { InitializeHook } from 'node:module';\nimport type { InitializationOptions } from '../api/register.js';\nimport type { Message } from '../types.js';\nimport { loadTsconfig } from '../../utils/tsconfig.js';\n\ntype Data = InitializationOptions & {\n\tactive: boolean;\n};\n\nexport const data: Data = {\n\tactive: true,\n};\n\nexport const initialize: InitializeHook = async (\n\toptions?: InitializationOptions,\n) => {\n\tif (!options) {\n\t\tthrow new Error('tsx must be loaded with --import instead of --loader\\nThe --loader flag was deprecated in Node v20.6.0 and v18.19.0');\n\t}\n\n\tdata.namespace = options.namespace;\n\n\tif (options.tsconfig !== false) {\n\t\tloadTsconfig(options.tsconfig ?? process.env.TSX_TSCONFIG_PATH);\n\t}\n\n\tif (options.port) {\n\t\tdata.port = options.port;\n\n\t\t// Unregister\n\t\toptions.port.on('message', (message: string) => {\n\t\t\tif (message === 'deactivate') {\n\t\t\t\tdata.active = false;\n\t\t\t\toptions.port!.postMessage({ type: 'deactivated' } satisfies Message);\n\t\t\t}\n\t\t});\n\t}\n};\n\ntype GlobalPreloadHook = () => string;\n\n// Replaced by `initialize` in Node v20.6.0, v18.19.0\nexport const globalPreload: GlobalPreloadHook = () => {\n\tloadTsconfig(process.env.TSX_TSCONFIG_PATH);\n\treturn 'process.setSourceMapsEnabled(true);';\n};\n"
  },
  {
    "path": "src/esm/hook/load.ts",
    "content": "import { fileURLToPath } from 'node:url';\nimport path from 'node:path';\nimport type { LoadHook } from 'node:module';\nimport { readFile } from 'node:fs/promises';\nimport type { TransformOptions } from 'esbuild';\nimport { transform, transformSync } from '../../utils/transform/index.js';\nimport { transformDynamicImport } from '../../utils/transform/transform-dynamic-import.js';\nimport { inlineSourceMap } from '../../source-map.js';\nimport { isFeatureSupported, importAttributes, esmLoadReadFile } from '../../utils/node-features.js';\nimport { parent } from '../../utils/ipc/client.js';\nimport type { Message } from '../types.js';\nimport { fileMatcher } from '../../utils/tsconfig.js';\nimport { isJsonPattern, tsExtensionsPattern, fileUrlPrefix } from '../../utils/path-utils.js';\nimport { isESM } from '../../utils/es-module-lexer.js';\nimport { logEsm as log, debugEnabled } from '../../utils/debug.js';\nimport { getNamespace } from './utils.js';\nimport { data } from './initialize.js';\n\nconst importAttributesProperty = (\n\tisFeatureSupported(importAttributes)\n\t\t? 'importAttributes'\n\t\t: 'importAssertions' as 'importAttributes'\n);\n\n// eslint-disable-next-line import-x/no-mutable-exports\nlet load: LoadHook = async (\n\turl,\n\tcontext,\n\tnextLoad,\n) => {\n\tif (!data.active) {\n\t\treturn nextLoad(url, context);\n\t}\n\n\tconst urlNamespace = getNamespace(url);\n\tif (data.namespace && data.namespace !== urlNamespace) {\n\t\treturn nextLoad(url, context);\n\t}\n\n\tif (data.port) {\n\t\tconst parsedUrl = new URL(url);\n\t\tparsedUrl.searchParams.delete('tsx-namespace');\n\t\tdata.port.postMessage({\n\t\t\ttype: 'load',\n\t\t\turl: parsedUrl.toString(),\n\t\t} satisfies Message);\n\t}\n\n\t/*\n\tFilter out node:*\n\tMaybe only handle files that start with file://\n\t*/\n\tif (parent.send) {\n\t\tparent.send({\n\t\t\ttype: 'dependency',\n\t\t\tpath: url,\n\t\t});\n\t}\n\n\tif (isJsonPattern.test(url)) {\n\t\tlet contextAttributes = context[importAttributesProperty];\n\t\tif (!contextAttributes) {\n\t\t\tcontextAttributes = {};\n\t\t\tcontext[importAttributesProperty] = contextAttributes;\n\t\t}\n\n\t\tif (!contextAttributes.type) {\n\t\t\tcontextAttributes.type = 'json';\n\t\t}\n\t}\n\n\tconst loaded = await nextLoad(url, context);\n\tlog(3, 'loaded by next loader', {\n\t\turl,\n\t\tloaded,\n\t});\n\n\tconst filePath = url.startsWith(fileUrlPrefix) ? fileURLToPath(url) : url;\n\n\tif (\n\t\tloaded.format === 'commonjs'\n\t\t&& isFeatureSupported(esmLoadReadFile)\n\t\t&& loaded.responseURL?.startsWith('file:') // Could be data:\n\t\t&& !filePath.endsWith('.cjs') // CJS syntax doesn't need to be transformed for interop\n\t) {\n\t\tconst code = await readFile(new URL(url), 'utf8');\n\n\t\t// if the file extension is .js, only transform if using esm syntax\n\t\tif (!filePath.endsWith('.js') || isESM(code)) {\n\t\t\t/**\n\t\t\t * es or cjs module lexer unfortunately cannot be used because it doesn't support\n\t\t\t * typescript syntax\n\t\t\t *\n\t\t\t * While the full code is transformed, only the exports are used for parsing.\n\t\t\t * In fact, the code can't even run because imports cannot be resolved relative\n\t\t\t * from the data: URL.\n\t\t\t *\n\t\t\t * This should pre-compile for the CJS loader to have a cache hit\n\t\t\t *\n\t\t\t * I considered extracting the CJS exports from esbuild via (0&&(module.exports={})\n\t\t\t * to minimize the data URL size but this only works for ESM->CJS and not CTS files\n\t\t\t * which are already in CJS syntax.\n\t\t\t * In CTS, module.exports can be written in any pattern.\n\t\t\t */\n\t\t\tconst transformed = transformSync(\n\t\t\t\tcode,\n\t\t\t\tfilePath,\n\t\t\t\t{\n\t\t\t\t\ttsconfigRaw: fileMatcher?.(filePath) as TransformOptions['tsconfigRaw'],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst filePathWithNamespace = urlNamespace ? `${filePath}?namespace=${encodeURIComponent(urlNamespace)}` : filePath;\n\n\t\t\tloaded.responseURL = `data:text/javascript,${encodeURIComponent(transformed.code)}?filePath=${encodeURIComponent(filePathWithNamespace)}`;\n\n\t\t\tlog(3, 'returning CJS export annotation', loaded);\n\t\t\treturn loaded;\n\t\t}\n\t}\n\n\t// CommonJS and Internal modules (e.g. node:*)\n\tif (!loaded.source) {\n\t\treturn loaded;\n\t}\n\n\tconst code = loaded.source.toString();\n\n\tif (\n\t\t// Support named imports in JSON modules\n\t\tloaded.format === 'json'\n\t\t|| tsExtensionsPattern.test(url)\n\t) {\n\t\tconst transformed = await transform(\n\t\t\tcode,\n\t\t\tfilePath,\n\t\t\t{\n\t\t\t\ttsconfigRaw: (\n\t\t\t\t\tpath.isAbsolute(filePath)\n\t\t\t\t\t\t? fileMatcher?.(filePath) as TransformOptions['tsconfigRaw']\n\t\t\t\t\t\t: undefined\n\t\t\t\t),\n\t\t\t},\n\t\t);\n\n\t\treturn {\n\t\t\tformat: 'module',\n\t\t\tsource: inlineSourceMap(transformed),\n\t\t};\n\t}\n\n\tif (loaded.format === 'module') {\n\t\tconst dynamicImportTransformed = transformDynamicImport(filePath, code);\n\t\tif (dynamicImportTransformed) {\n\t\t\tloaded.source = inlineSourceMap(dynamicImportTransformed);\n\t\t}\n\t}\n\n\treturn loaded;\n};\n\nif (debugEnabled) {\n\tconst originalLoad = load;\n\tload = async (\n\t\turl,\n\t\tcontext,\n\t\tnextLoad,\n\t) => {\n\t\tlog(2, 'load', {\n\t\t\turl,\n\t\t\tcontext,\n\t\t});\n\t\tconst result = await originalLoad(url, context, nextLoad);\n\t\tlog(1, 'loaded', {\n\t\t\turl,\n\t\t\tresult,\n\t\t});\n\t\treturn result;\n\t};\n}\n\nexport { load };\n"
  },
  {
    "path": "src/esm/hook/package-json.ts",
    "content": "import fs from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport type { PackageJson } from 'type-fest';\n\nconst packageJsonCache = new Map<string, PackageJson | undefined>();\nconst readPackageJson = async (filePath: string) => {\n\tif (packageJsonCache.has(filePath)) {\n\t\treturn packageJsonCache.get(filePath);\n\t}\n\n\tconst exists = await fs.promises.access(filePath).then(\n\t\t() => true,\n\t\t() => false,\n\t);\n\n\tif (!exists) {\n\t\tpackageJsonCache.set(filePath, undefined);\n\t\treturn;\n\t}\n\n\tconst packageJsonString = await fs.promises.readFile(filePath, 'utf8');\n\ttry {\n\t\tconst packageJson = JSON.parse(packageJsonString) as PackageJson;\n\t\tpackageJsonCache.set(filePath, packageJson);\n\t\treturn packageJson;\n\t} catch {\n\t\tthrow new Error(`Error parsing: ${filePath}`);\n\t}\n};\n\n// From Node.js\n// https://github.com/nodejs/node/blob/e86a6383054623e5168384a83d8cd6ebfe1fb584/lib/internal/modules/esm/resolve.js#L229\nconst findPackageJson = async (\n\tfilePath: string,\n) => {\n\tlet packageJsonUrl = new URL('package.json', filePath);\n\n\twhile (true) {\n\t\t// Don't look outside of /node_modules/\n\t\tif (packageJsonUrl.pathname.endsWith('/node_modules/package.json')) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst packageJsonPath = fileURLToPath(packageJsonUrl);\n\t\tconst packageJson = await readPackageJson(packageJsonPath);\n\n\t\tif (packageJson) {\n\t\t\treturn packageJson;\n\t\t}\n\n\t\tconst lastPackageJSONUrl = packageJsonUrl;\n\t\tpackageJsonUrl = new URL('../package.json', packageJsonUrl);\n\n\t\t// Terminates at root where ../package.json equals ../../package.json\n\t\t// (can't just check \"/package.json\" for Windows support).\n\t\tif (packageJsonUrl.pathname === lastPackageJSONUrl.pathname) {\n\t\t\tbreak;\n\t\t}\n\t}\n};\n\nexport const getPackageType = async (\n\tfilePath: string,\n) => {\n\tconst packageJson = await findPackageJson(filePath);\n\treturn packageJson?.type ?? 'commonjs';\n};\n"
  },
  {
    "path": "src/esm/hook/resolve.ts",
    "content": "import path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type {\n\tResolveHook,\n\tResolveHookContext,\n} from 'node:module';\nimport type { PackageJson } from 'type-fest';\nimport { readJsonFile } from '../../utils/read-json-file.js';\nimport { mapTsExtensions } from '../../utils/map-ts-extensions.js';\nimport type { NodeError } from '../../types.js';\nimport { tsconfigPathsMatcher, allowJs } from '../../utils/tsconfig.js';\nimport {\n\trequestAcceptsQuery,\n\tfileUrlPrefix,\n\ttsExtensionsPattern,\n\tisDirectoryPattern,\n\tisRelativePath,\n} from '../../utils/path-utils.js';\nimport type { TsxRequest } from '../types.js';\nimport { logEsm as log, debugEnabled } from '../../utils/debug.js';\nimport {\n\tgetFormatFromFileUrl,\n\tnamespaceQuery,\n\tgetNamespace,\n} from './utils.js';\nimport { data } from './initialize.js';\n\ntype NextResolve = Parameters<ResolveHook>[2];\n\nconst getMissingPathFromNotFound = (\n\tnodeError: NodeError,\n) => {\n\tif (nodeError.url) {\n\t\treturn nodeError.url;\n\t}\n\n\tconst isExportPath = nodeError.message.match(/^Cannot find module '([^']+)'/);\n\tif (isExportPath) {\n\t\tconst [, exportPath] = isExportPath;\n\t\treturn exportPath;\n\t}\n\n\tconst isPackagePath = nodeError.message.match(/^Cannot find package '([^']+)'/);\n\tif (isPackagePath) {\n\t\tconst [, packagePath] = isPackagePath;\n\t\tif (!path.isAbsolute(packagePath)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst packageUrl = pathToFileURL(packagePath);\n\n\t\t// Node v20.0.0 logs the package directory\n\t\t// Slash check / works on Windows as well because it's a path URL\n\t\tif (packageUrl.pathname.endsWith('/')) {\n\t\t\tpackageUrl.pathname += 'package.json';\n\t\t}\n\n\t\t// Node v21+ logs the package package.json path\n\t\tif (packageUrl.pathname.endsWith('/package.json')) {\n\t\t\t// packageJsonUrl.pathname += '/package.json';\n\t\t\tconst packageJson = readJsonFile<PackageJson>(packageUrl);\n\t\t\tif (packageJson?.main) {\n\t\t\t\treturn new URL(packageJson.main, packageUrl).toString();\n\t\t\t}\n\t\t} else {\n\t\t\t// Node v22.6.0 logs the entry path so we don't need to look it up from package.json\n\t\t\treturn packageUrl.toString();\n\t\t}\n\t}\n};\n\nconst resolveExtensions = async (\n\turl: string,\n\tcontext: ResolveHookContext,\n\tnextResolve: NextResolve,\n\tthrowError?: boolean,\n) => {\n\tconst tryPaths = mapTsExtensions(url);\n\tlog(3, 'resolveExtensions', {\n\t\turl,\n\t\tcontext,\n\t\tthrowError,\n\t\ttryPaths,\n\t});\n\tif (!tryPaths) {\n\t\treturn;\n\t}\n\n\tlet caughtError: unknown;\n\tfor (const tsPath of tryPaths) {\n\t\ttry {\n\t\t\treturn await nextResolve(tsPath, context);\n\t\t} catch (error) {\n\t\t\tconst { code } = error as NodeError;\n\t\t\tif (\n\t\t\t\tcode !== 'ERR_MODULE_NOT_FOUND'\n\t\t\t\t&& code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED'\n\t\t\t) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tcaughtError = error;\n\t\t}\n\t}\n\n\tif (throwError) {\n\t\tthrow caughtError;\n\t}\n};\n\nconst resolveBase: ResolveHook = async (\n\tspecifier,\n\tcontext,\n\tnextResolve,\n) => {\n\tlog(3, 'resolveBase', {\n\t\tspecifier,\n\t\tcontext,\n\t\tspecifierStartsWithFileUrl: specifier.startsWith(fileUrlPrefix),\n\t\tisRelativePath: isRelativePath(specifier),\n\t\ttsExtensionsPattern: tsExtensionsPattern.test(context.parentURL!),\n\t\tallowJs,\n\t});\n\n\t/**\n\t * Only prioritize TypeScript extensions for file paths (no dependencies)\n\t * TS aliases are pre-resolved so they're file paths\n\t *\n\t * If `allowJs` is set in `tsconfig.json`, then we'll apply the same resolution logic\n\t * to files without a TypeScript extension.\n\t */\n\tif (\n\t\t(\n\t\t\tspecifier.startsWith(fileUrlPrefix)\n\t\t\t|| isRelativePath(specifier)\n\t\t) && (\n\t\t\ttsExtensionsPattern.test(context.parentURL!)\n\t\t\t|| allowJs\n\t\t)\n\t) {\n\t\tconst resolved = await resolveExtensions(specifier, context, nextResolve);\n\t\tlog(3, 'resolveBase resolved', {\n\t\t\tspecifier,\n\t\t\tcontext,\n\t\t\tresolved,\n\t\t});\n\t\tif (resolved) {\n\t\t\treturn resolved;\n\t\t}\n\t}\n\n\ttry {\n\t\treturn await nextResolve(specifier, context);\n\t} catch (error) {\n\t\tlog(3, 'resolveBase error', {\n\t\t\tspecifier,\n\t\t\tcontext,\n\t\t\terror,\n\t\t});\n\t\tif (error instanceof Error) {\n\t\t\tconst nodeError = error as NodeError;\n\t\t\tif (nodeError.code === 'ERR_MODULE_NOT_FOUND') {\n\t\t\t\t// Resolving .js -> .ts in exports/imports map\n\t\t\t\tconst errorPath = getMissingPathFromNotFound(nodeError);\n\t\t\t\tif (errorPath) {\n\t\t\t\t\tconst resolved = await resolveExtensions(errorPath, context, nextResolve);\n\t\t\t\t\tif (resolved) {\n\t\t\t\t\t\treturn resolved;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow error;\n\t}\n};\n\nconst resolveDirectory: ResolveHook = async (\n\tspecifier,\n\tcontext,\n\tnextResolve,\n) => {\n\tlog(3, 'resolveDirectory', {\n\t\tspecifier,\n\t\tcontext,\n\t\tisDirectory: isDirectoryPattern.test(specifier),\n\t});\n\tif (specifier === '.' || specifier === '..' || specifier.endsWith('/..')) {\n\t\tspecifier += '/';\n\t}\n\n\tif (isDirectoryPattern.test(specifier)) {\n\t\tconst urlParsed = new URL(specifier, context.parentURL);\n\n\t\t// If directory, can be index.js, index.ts, etc.\n\t\turlParsed.pathname = path.join(urlParsed.pathname, 'index');\n\n\t\treturn (await resolveExtensions(\n\t\t\turlParsed.toString(),\n\t\t\tcontext,\n\t\t\tnextResolve,\n\t\t\ttrue,\n\t\t))!;\n\t}\n\n\ttry {\n\t\treturn await resolveBase(specifier, context, nextResolve);\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tlog(3, 'resolveDirectory error', {\n\t\t\t\tspecifier,\n\t\t\t\tcontext,\n\t\t\t\terror,\n\t\t\t});\n\t\t\tconst nodeError = error as NodeError;\n\t\t\tif (nodeError.code === 'ERR_UNSUPPORTED_DIR_IMPORT') {\n\t\t\t\tconst errorPath = getMissingPathFromNotFound(nodeError);\n\t\t\t\tif (errorPath) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn (await resolveExtensions(\n\t\t\t\t\t\t\t`${errorPath}/index`,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tnextResolve,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t))!;\n\t\t\t\t\t} catch (_error) {\n\t\t\t\t\t\tconst __error = _error as Error;\n\t\t\t\t\t\tconst { message } = __error;\n\t\t\t\t\t\t__error.message = __error.message.replace(`${'/index'.replace('/', path.sep)}'`, \"'\");\n\t\t\t\t\t\t__error.stack = __error.stack!.replace(message, __error.message);\n\t\t\t\t\t\tthrow __error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow error;\n\t}\n};\n\nconst resolveTsPaths: ResolveHook = async (\n\tspecifier,\n\tcontext,\n\tnextResolve,\n) => {\n\tlog(3, 'resolveTsPaths', {\n\t\tspecifier,\n\t\tcontext,\n\n\t\trequestAcceptsQuery: requestAcceptsQuery(specifier),\n\t\ttsconfigPathsMatcher,\n\t\tfromNodeModules: context.parentURL?.includes('/node_modules/'),\n\t});\n\tif (\n\t\t// Bare specifier\n\t\t!requestAcceptsQuery(specifier)\n\t\t// TS path alias\n\t\t&& tsconfigPathsMatcher\n\t\t&& !context.parentURL?.includes('/node_modules/')\n\t) {\n\t\tconst possiblePaths = tsconfigPathsMatcher(specifier);\n\t\tlog(3, 'resolveTsPaths', {\n\t\t\tpossiblePaths,\n\t\t});\n\t\tfor (const possiblePath of possiblePaths) {\n\t\t\ttry {\n\t\t\t\treturn await resolveDirectory(\n\t\t\t\t\tpathToFileURL(possiblePath).toString(),\n\t\t\t\t\tcontext,\n\t\t\t\t\tnextResolve,\n\t\t\t\t);\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\treturn resolveDirectory(specifier, context, nextResolve);\n};\n\nconst tsxProtocol = 'tsx://';\n\n// eslint-disable-next-line import-x/no-mutable-exports\nlet resolve: ResolveHook = async (\n\tspecifier,\n\tcontext,\n\tnextResolve,\n) => {\n\tif (!data.active || specifier.startsWith('node:')) {\n\t\treturn nextResolve(specifier, context);\n\t}\n\n\tlet requestNamespace = getNamespace(specifier) ?? (\n\t\t// Inherit namespace from parent\n\t\tcontext.parentURL && getNamespace(context.parentURL)\n\t);\n\n\tif (data.namespace) {\n\t\tlet tsImportRequest: TsxRequest | undefined;\n\n\t\t// Initial request from tsImport()\n\t\tif (specifier.startsWith(tsxProtocol)) {\n\t\t\ttry {\n\t\t\t\ttsImportRequest = JSON.parse(specifier.slice(tsxProtocol.length));\n\t\t\t} catch {}\n\n\t\t\tif (tsImportRequest?.namespace) {\n\t\t\t\trequestNamespace = tsImportRequest.namespace;\n\t\t\t}\n\t\t}\n\n\t\tif (data.namespace !== requestNamespace) {\n\t\t\treturn nextResolve(specifier, context);\n\t\t}\n\n\t\tif (tsImportRequest) {\n\t\t\tspecifier = tsImportRequest.specifier;\n\t\t\tcontext.parentURL = tsImportRequest.parentURL;\n\t\t}\n\t}\n\n\tconst [cleanSpecifier, query] = specifier.split('?');\n\n\tconst resolved = await resolveTsPaths(\n\t\tcleanSpecifier,\n\t\tcontext,\n\t\tnextResolve,\n\t);\n\n\tlog(2, 'nextResolve', {\n\t\tresolved,\n\t});\n\n\tif (resolved.format === 'builtin') {\n\t\treturn resolved;\n\t}\n\n\t// For TypeScript extensions that Node can't detect the format of\n\tif (\n\t\t(\n\t\t\t!resolved.format\n\t\t\t|| resolved.format === 'commonjs-typescript'\n\t\t\t|| resolved.format === 'module-typescript'\n\t\t)\n\t\t// Filter out data: (sourcemaps)\n\t\t&& resolved.url.startsWith(fileUrlPrefix)\n\t) {\n\t\tresolved.format = await getFormatFromFileUrl(resolved.url);\n\t\tlog(2, 'getFormatFromFileUrl', {\n\t\t\tresolved,\n\t\t\tformat: resolved.format,\n\t\t});\n\t}\n\n\tif (query) {\n\t\tresolved.url += `?${query}`;\n\t}\n\n\t// Inherit namespace\n\tif (\n\t\trequestNamespace\n\t\t&& !resolved.url.includes(namespaceQuery)\n\t) {\n\t\tresolved.url += (resolved.url.includes('?') ? '&' : '?') + namespaceQuery + requestNamespace;\n\t}\n\n\treturn resolved;\n};\n\nif (debugEnabled) {\n\tconst originalResolve = resolve;\n\tresolve = async (\n\t\tspecifier,\n\t\tcontext,\n\t\tnextResolve,\n\t) => {\n\t\tlog(2, 'resolve', {\n\t\t\tspecifier,\n\t\t\tcontext,\n\t\t});\n\t\tconst result = await originalResolve(specifier, context, nextResolve);\n\t\tlog(1, 'resolved', {\n\t\t\tspecifier,\n\t\t\tcontext,\n\t\t\tresult,\n\t\t});\n\t\treturn result;\n\t};\n}\n\nexport { resolve };\n"
  },
  {
    "path": "src/esm/hook/utils.ts",
    "content": "import path from 'node:path';\nimport { tsExtensions } from '../../utils/path-utils.js';\nimport { getPackageType } from './package-json.js';\n\nexport const getFormatFromFileUrl = (fileUrl: string) => {\n\tconst { pathname } = new URL(fileUrl);\n\tconst extension = path.extname(pathname);\n\tif (extension === '.mts' || extension === '.mjs') {\n\t\treturn 'module';\n\t}\n\tif (extension === '.cts' || extension === '.cjs') {\n\t\treturn 'commonjs';\n\t}\n\n\tif (extension === '.js' || tsExtensions.includes(extension)) {\n\t\treturn getPackageType(fileUrl);\n\t}\n};\n\nexport const namespaceQuery = 'tsx-namespace=';\nexport const getNamespace = (\n\turl: string,\n) => {\n\tconst index = url.indexOf(namespaceQuery);\n\tif (index === -1) {\n\t\treturn;\n\t}\n\n\tconst charBefore = url[index - 1];\n\tif (charBefore !== '?' && charBefore !== '&') {\n\t\treturn;\n\t}\n\n\tconst startIndex = index + namespaceQuery.length;\n\tconst endIndex = url.indexOf('&', startIndex);\n\n\treturn (\n\t\tendIndex === -1\n\t\t\t? url.slice(startIndex)\n\t\t\t: url.slice(startIndex, endIndex)\n\t);\n};\n"
  },
  {
    "path": "src/esm/index.ts",
    "content": "import { isMainThread } from 'node:worker_threads';\nimport { isFeatureSupported, moduleRegister } from '../utils/node-features.js';\nimport { register } from './api/index.js';\n\n// Loaded via --import flag\nif (\n\tisFeatureSupported(moduleRegister)\n\t&& isMainThread\n) {\n\tregister();\n}\n\nexport * from './hook/index.js';\n"
  },
  {
    "path": "src/esm/types.ts",
    "content": "export type Message = {\n\ttype: 'deactivated';\n} | {\n\ttype: 'load';\n\turl: string;\n};\n\nexport type TsxRequest = {\n\tnamespace: string;\n\tparentURL: string;\n\tspecifier: string;\n};\n"
  },
  {
    "path": "src/loader.ts",
    "content": "// Hook require() to transform to CJS\n// eslint-disable-next-line import-x/no-unresolved, @typescript-eslint/no-require-imports\nrequire('./cjs/index.cjs');\n\n/*\nHook import/import() to transform to ESM\nCan be used in Node v12 to support dynamic `import()`\n*/\nexport * from './esm/index.js';\n"
  },
  {
    "path": "src/patch-repl.ts",
    "content": "import repl, { type REPLServer, type REPLEval } from 'node:repl';\nimport { transform } from 'esbuild';\n\nconst patchEval = (nodeRepl: REPLServer) => {\n\tconst { eval: defaultEval } = nodeRepl;\n\tconst preEval: REPLEval = async function (code, context, filename, callback) {\n\t\ttry {\n\t\t\tconst transformed = await transform(\n\t\t\t\tcode,\n\t\t\t\t{\n\t\t\t\t\tsourcefile: filename,\n\t\t\t\t\tloader: 'ts',\n\t\t\t\t\ttsconfigRaw: {\n\t\t\t\t\t\tcompilerOptions: {\n\t\t\t\t\t\t\tpreserveValueImports: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tdefine: {\n\t\t\t\t\t\trequire: 'global.require',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tcode = transformed.code;\n\t\t} catch {}\n\n\t\treturn defaultEval.call(this, code, context, filename, callback);\n\t};\n\n\t// @ts-expect-error overwriting read-only property\n\tnodeRepl.eval = preEval;\n};\n\nconst { start } = repl;\nrepl.start = function () {\n\tconst nodeRepl = Reflect.apply(start, this, arguments);\n\tpatchEval(nodeRepl);\n\treturn nodeRepl;\n};\n"
  },
  {
    "path": "src/preflight.cts",
    "content": "import { constants as osConstants } from 'node:os';\nimport { isMainThread } from 'node:worker_threads';\nimport { connectingToServer } from './utils/ipc/client.js';\nimport './suppress-warnings.cjs';\n\ntype BaseEventListener = () => void;\n\nconst bindHiddenSignalsHandler = (\n\tsignals: NodeJS.Signals[],\n\thandler: NodeJS.SignalsListener,\n) => {\n\ttype RelaySignals = typeof signals[number];\n\n\tconst hiddenHandlers = new Map<RelaySignals, NodeJS.SignalsListener>();\n\tfor (const signal of signals) {\n\t\tconst hiddenHandler = (receivedSignal: NodeJS.Signals) => {\n\t\t\thandler(receivedSignal);\n\n\t\t\t/**\n\t\t\t * Since we're setting a custom signal handler, we need to emulate the\n\t\t\t * default behavior when there are no other handlers set\n\t\t\t */\n\t\t\tif (process.listenerCount(signal) === 0) {\n\t\t\t\t// eslint-disable-next-line n/no-process-exit\n\t\t\t\tprocess.exit(128 + osConstants.signals[signal]);\n\t\t\t}\n\t\t};\n\n\t\tprocess.on(signal, hiddenHandler);\n\t\thiddenHandlers.set(signal, hiddenHandler);\n\t}\n\n\t/**\n\t * Hide relaySignal from process.listeners() and process.listenerCount()\n\t */\n\tconst { listenerCount, listeners } = process;\n\n\tprocess.listenerCount = function (eventName) {\n\t\tlet count = Reflect.apply(listenerCount, this, arguments);\n\t\tif (signals.includes(eventName as RelaySignals)) {\n\t\t\tcount -= 1;\n\t\t}\n\t\treturn count;\n\t};\n\n\tprocess.listeners = function (eventName) {\n\t\tconst result: BaseEventListener[] = Reflect.apply(listeners, this, arguments);\n\t\tif (signals.includes(eventName as RelaySignals)) {\n\t\t\treturn result.filter(\n\t\t\t\tlistener => listener !== hiddenHandlers.get(eventName as RelaySignals),\n\t\t\t);\n\t\t}\n\t\treturn result;\n\t};\n};\n\n/**\n * Seems module.register() calls the loader with the same Node arguments\n * which causes this preflight to be loaded in the loader thread\n */\nif (isMainThread) {\n\t/**\n\t * Hook require() to transform to CJS\n\t *\n\t * This needs to be loaded via --require flag so subsequent --require\n\t * flags can support TypeScript.\n\t *\n\t * This is also added in loader.ts for the loader API.\n\t * Although it is required twice, it's not executed twice because\n\t * it's cached.\n\t */\n\t// eslint-disable-next-line import-x/no-unresolved, @typescript-eslint/no-require-imports\n\trequire('./cjs/index.cjs');\n\n\t(async () => {\n\t\tconst sendToParent = await connectingToServer;\n\n\t\tif (sendToParent) {\n\t\t\tbindHiddenSignalsHandler(['SIGINT', 'SIGTERM'], (signal: NodeJS.Signals) => {\n\t\t\t\tsendToParent({\n\t\t\t\t\ttype: 'signal',\n\t\t\t\t\tsignal,\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t})();\n}\n"
  },
  {
    "path": "src/remove-argv-flags.ts",
    "content": "import {\n\ttypeFlag,\n\ttype Flags,\n\ttype TypeFlagOptions,\n} from 'type-flag';\n\nexport const ignoreAfterArgument = (\n\tignoreFirstArgument = true, // Used for watch\n): TypeFlagOptions['ignore'] => {\n\tlet ignore = false;\n\n\treturn (type) => {\n\t\tif (\n\t\t\tignore\n\t\t\t|| type === 'unknown-flag'\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (type === 'argument') {\n\t\t\tignore = true;\n\t\t\treturn ignoreFirstArgument;\n\t\t}\n\t};\n};\n\nexport const removeArgvFlags = (\n\ttsxFlags: Flags,\n\targv = process.argv.slice(2),\n) => {\n\ttypeFlag(\n\t\ttsxFlags,\n\t\targv,\n\t\t{\n\t\t\tignore: ignoreAfterArgument(),\n\t\t},\n\t);\n\n\treturn argv;\n};\n"
  },
  {
    "path": "src/repl.ts",
    "content": "// Deprecated: Delete entry-point in next major in favor of patch-repl.ts\n\nimport repl, { type REPLEval } from 'node:repl';\nimport { version } from '../package.json';\nimport { transform } from './utils/transform/index.js';\n\n// Copied from\n// https://github.com/nodejs/node/blob/v18.2.0/lib/internal/main/repl.js#L37\nconsole.log(\n\t`Welcome to tsx v${version} (Node.js ${process.version}).\\n`\n      + 'Type \".help\" for more information.',\n);\n\nconst nodeRepl = repl.start();\n\nconst { eval: defaultEval } = nodeRepl;\n\nconst preEval: REPLEval = async function (code, context, filename, callback) {\n\tconst transformed = await transform(\n\t\tcode,\n\t\tfilename,\n\t\t{\n\t\t\tloader: 'ts',\n\t\t\ttsconfigRaw: {\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\tpreserveValueImports: true,\n\t\t\t\t},\n\t\t\t},\n\t\t\tdefine: {\n\t\t\t\trequire: 'global.require',\n\t\t\t},\n\t\t},\n\t).catch(\n\t\t(error) => {\n\t\t\tconsole.log(error.message);\n\t\t\treturn { code: '\\n' };\n\t\t},\n\t);\n\n\treturn defaultEval.call(this, transformed.code, context, filename, callback);\n};\n\n// @ts-expect-error overriding read-only property\nnodeRepl.eval = preEval;\n"
  },
  {
    "path": "src/run.ts",
    "content": "import type { StdioOptions } from 'node:child_process';\nimport { pathToFileURL } from 'node:url';\nimport spawn from 'cross-spawn';\nimport { isFeatureSupported, moduleRegister } from './utils/node-features.js';\n\nexport const run = (\n\targv: string[],\n\toptions?: {\n\t\tnoCache?: boolean;\n\t\ttsconfigPath?: string;\n\t\tipc?: boolean;\n\t},\n) => {\n\tconst environment = { ...process.env };\n\tconst stdio: StdioOptions = [\n\t\t'inherit', // stdin\n\t\t'inherit', // stdout\n\t\t'inherit', // stderr\n\t];\n\n\t// If parent process spawns tsx with ipc, spawn child with ipc\n\tif (process.send) {\n\t\tstdio.push('ipc');\n\t}\n\n\tif (options) {\n\t\tif (options.noCache) {\n\t\t\tenvironment.TSX_DISABLE_CACHE = '1';\n\t\t}\n\n\t\tif (options.tsconfigPath) {\n\t\t\tenvironment.TSX_TSCONFIG_PATH = options.tsconfigPath;\n\t\t}\n\t}\n\n\tconst shouldPatchRepl = argv.filter(flag => (flag !== '-i' && flag !== '--interactive')).length === 0;\n\n\treturn spawn(\n\t\tprocess.execPath,\n\t\t[\n\t\t\t'--require',\n\t\t\trequire.resolve('./preflight.cjs'),\n\n\t\t\t...(\n\t\t\t\tshouldPatchRepl\n\t\t\t\t\t? [\n\t\t\t\t\t\t'--require',\n\t\t\t\t\t\trequire.resolve('./patch-repl.cjs'),\n\t\t\t\t\t]\n\t\t\t\t\t: []\n\t\t\t),\n\n\t\t\tisFeatureSupported(moduleRegister) ? '--import' : '--loader',\n\t\t\tpathToFileURL(require.resolve('./loader.mjs')).toString(),\n\n\t\t\t...argv,\n\t\t],\n\t\t{\n\t\t\tstdio,\n\t\t\tenv: environment,\n\t\t},\n\t);\n};\n"
  },
  {
    "path": "src/source-map.ts",
    "content": "import type { Transformed } from './utils/transform/apply-transformers.js';\n\nconst inlineSourceMapPrefix = '\\n//# sourceMappingURL=data:application/json;base64,';\n\n// TODO: Build this logic into inlineSourceMap\n// If undefined, assume sourcemap is enabled\nexport const shouldApplySourceMap = () => process.sourceMapsEnabled ?? true;\n\nexport const inlineSourceMap = (\n\t{ code, map }: Transformed,\n) => (\n\tcode\n\t+ inlineSourceMapPrefix\n\t+ Buffer.from(JSON.stringify(map), 'utf8').toString('base64')\n);\n"
  },
  {
    "path": "src/suppress-warnings.cts",
    "content": "// Deprecated: Move to preflight.cts & delete entry-point in next major\n\nconst ignoreWarnings = new Set([\n\n\t// v18.0.0\n\t'Custom ESM Loaders is an experimental feature. This feature could change at any time',\n\n\t// Changed in Node v18.13.0 via https://github.com/nodejs/node/pull/45424\n\t'Custom ESM Loaders is an experimental feature and might change at any time',\n\n\t// For JSON modules via https://github.com/nodejs/node/pull/46901\n\t'Import assertions are not a stable feature of the JavaScript language. Avoid relying on their current behavior and syntax as those might change in a future version of Node.js.',\n]);\n\nconst { emit } = process;\n\n// @ts-expect-error emit type mismatch\nprocess.emit = function (event: 'warning', warning: Error) {\n\tif (\n\t\tevent === 'warning'\n\t\t&& ignoreWarnings.has(warning.message)\n\t) {\n\t\treturn;\n\t}\n\n\treturn Reflect.apply(emit, this, arguments);\n};\n"
  },
  {
    "path": "src/types.ts",
    "content": "export type NodeError = Error & {\n\tcode: string;\n\turl?: string;\n\tpath?: string;\n};\n\nexport type RequiredProperty<Type, Keys extends keyof Type> = Type & { [P in Keys]-?: Type[P] };\n"
  },
  {
    "path": "src/utils/debug.ts",
    "content": "import { inspect } from 'node:util';\nimport { writeSync } from 'node:fs';\nimport {\n\toptions, bgBlue, black, bgLightYellow, bgGray,\n} from 'kolorist';\n\nexport const debugEnabled = Number(process.env.TSX_DEBUG);\n\n// Force colors in debug mode\nif (debugEnabled) {\n\toptions.enabled = true;\n\toptions.supportLevel = 3;\n}\n\nconst createLog = (\n\tname: string,\n) => (\n\tlevel: number,\n\t...args: any[]\n) => {\n\tif (!debugEnabled) {\n\t\treturn;\n\t}\n\n\tif (level > debugEnabled) {\n\t\treturn;\n\t}\n\n\tconst prefix = `${bgGray(` tsx P${process.pid} `)} ${name}`;\n\tconst logMessage = args.map(argumentElement => (\n\t\ttypeof argumentElement === 'string'\n\t\t\t? argumentElement\n\t\t\t: inspect(argumentElement, { colors: true })\n\t)).join(' ');\n\n\twriteSync(\n\t\t1,\n\t\t`${prefix} ${logMessage}\\n`,\n\t);\n};\n\nexport const logCjs = createLog(bgLightYellow(black(' CJS ')));\nexport const logEsm = createLog(bgBlue(' ESM '));\n\nexport const time = <T extends (...args: any[]) => unknown>(\n\tname: string,\n\t_function: T,\n\tthreshold = 100,\n): T => function (\n\t\tthis: unknown,\n\t\t...args: Parameters<T>\n\t) {\n\t\tconst timeStart = Date.now();\n\t\tconst logTimeElapsed = () => {\n\t\t\tconst elapsed = Date.now() - timeStart;\n\n\t\t\tif (elapsed > threshold) {\n\t\t\t\tconsole.log(name, {\n\t\t\t\t\targs,\n\t\t\t\t\telapsed,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tconst result = Reflect.apply(_function, this, args);\n\t\tif (\n\t\t\tresult\n\t\t&& typeof result === 'object'\n\t\t&& 'then' in result\n\t\t) {\n\t\t\t(result as Promise<unknown>).then(\n\t\t\t\tlogTimeElapsed,\n\t\t\t\t// Ignore error in this chain\n\t\t\t\t() => {},\n\t\t\t);\n\t\t} else {\n\t\t\tlogTimeElapsed();\n\t\t}\n\t\treturn result;\n\t} as T;\n"
  },
  {
    "path": "src/utils/es-module-lexer.ts",
    "content": "import { parse as parseJs } from 'es-module-lexer/js';\n\nlet parseWasm: typeof import('es-module-lexer').parse | undefined;\n\n// When Node's --jitless flag is set, WebAssembly is not available\nif (typeof WebAssembly !== 'undefined') {\n\t(async () => {\n\t\tconst { parse, init } = await import('es-module-lexer');\n\t\tawait init;\n\t\tparseWasm = parse;\n\t})();\n}\n\nexport const parseEsm = (\n\tcode: string,\n\tfilename?: string,\n) => (\n\tparseWasm\n\t\t? parseWasm(code, filename)\n\t\t: parseJs(code, filename)\n);\n\n/*\nPreviously, this regex was used as a naive ESM catch,\nbut turns out regex is slower than the lexer so removing\nit made the check faster.\n\nCatches:\nimport a from 'b'\nimport 'b';\nimport('b');\nexport{a};\nexport default a;\n\nDoesn't catch:\nEXPORT{a}\nexports.a = 1\nmodule.exports = 1\n\nconst esmPattern = /\\b(?:import|export)\\b/;\n*/\n\nexport const isESM = (code: string) => {\n\tif (!code.includes('import') && !code.includes('export')) {\n\t\treturn false;\n\t}\n\ttry {\n\t\tconst hasModuleSyntax = parseEsm(code)[3];\n\t\treturn hasModuleSyntax;\n\t} catch {\n\t\t/**\n\t\t * If it fails to parse, there's a syntax error\n\t\t * Let esbuild handle it for better error messages\n\t\t */\n\t\treturn true;\n\t}\n};\n"
  },
  {
    "path": "src/utils/ipc/client.ts",
    "content": "import net from 'node:net';\nimport { getPipePath } from './get-pipe-path.js';\n\nexport type SendToParent = (data: Record<string, unknown>) => void;\n\nexport type Parent = {\n\tsend: SendToParent | void;\n};\n\nconst connectToServer = () => new Promise<SendToParent | void>((resolve) => {\n\tconst pipePath = getPipePath(process.ppid);\n\tconst socket: net.Socket = net.createConnection(\n\t\tpipePath,\n\t\t() => {\n\t\t\tconst sendToParent: SendToParent = (data) => {\n\t\t\t\tconst messageBuffer = Buffer.from(JSON.stringify(data));\n\t\t\t\tconst lengthBuffer = Buffer.alloc(4);\n\t\t\t\tlengthBuffer.writeInt32BE(messageBuffer.length, 0);\n\t\t\t\tsocket.write(Buffer.concat([lengthBuffer, messageBuffer]));\n\t\t\t};\n\t\t\tresolve(sendToParent);\n\t\t},\n\t);\n\n\t/**\n\t * Ignore error when:\n\t * - Called as a loader and there is no server\n\t * - Nested process when using --test and the ppid is incorrect\n\t */\n\tsocket.on('error', () => {\n\t\tresolve();\n\t});\n\n\t// Prevent Node from waiting for this socket to close before exiting\n\tsocket.unref();\n});\n\nexport const parent: Parent = {\n\tsend: undefined,\n};\n\nexport const connectingToServer = connectToServer();\n\nconnectingToServer.then(\n\t(send) => {\n\t\tparent.send = send;\n\t},\n\t() => {},\n);\n"
  },
  {
    "path": "src/utils/ipc/get-pipe-path.ts",
    "content": "import path from 'node:path';\nimport { tmpdir } from '../temporary-directory.js';\nimport { isWindows } from '../is-windows.js';\n\nexport const getPipePath = (processId: number) => {\n\tconst pipePath = path.join(tmpdir, `${processId}.pipe`);\n\treturn (\n\t\tisWindows\n\t\t\t? `\\\\\\\\?\\\\pipe\\\\${pipePath}`\n\t\t\t: pipePath\n\t);\n};\n"
  },
  {
    "path": "src/utils/ipc/server.ts",
    "content": "import net from 'node:net';\nimport fs from 'node:fs';\nimport { tmpdir } from '../temporary-directory.js';\nimport { isWindows } from '../is-windows.js';\nimport { getPipePath } from './get-pipe-path.js';\n\ntype OnMessage = (message: Buffer) => void;\n\nconst bufferData = (\n\tonMessage: OnMessage,\n) => {\n\tlet buffer = Buffer.alloc(0);\n\treturn (data: Buffer) => {\n\t\tbuffer = Buffer.concat([buffer, data]);\n\n\t\twhile (buffer.length > 4) {\n\t\t\tconst messageLength = buffer.readInt32BE(0);\n\t\t\tif (buffer.length >= 4 + messageLength) {\n\t\t\t\tconst message = buffer.slice(4, 4 + messageLength);\n\t\t\t\tonMessage(message);\n\t\t\t\tbuffer = buffer.slice(4 + messageLength);\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t};\n};\n\nexport const createIpcServer = async () => {\n\tconst server = net.createServer((socket) => {\n\t\tsocket.on('data', bufferData((message: Buffer) => {\n\t\t\tconst data = JSON.parse(message.toString());\n\t\t\tserver.emit('data', data);\n\t\t}));\n\t});\n\n\tconst pipePath = getPipePath(process.pid);\n\tawait fs.promises.mkdir(tmpdir, { recursive: true });\n\n\t/**\n\t * Fix #457 (https://github.com/privatenumber/tsx/issues/457)\n\t *\n\t * Avoid the error \"EADDRINUSE: address already in use\"\n\t *\n\t * If the pipe file already exists, it means that the previous process has been closed abnormally.\n\t *\n\t * We can safely delete the pipe file, the previous process must has been closed,\n\t * as pid is unique at the same.\n\t */\n\tawait fs.promises.rm(pipePath, {\n\t\tforce: true,\n\t});\n\n\tawait new Promise<void>((resolve, reject) => {\n\t\tserver.listen(pipePath, resolve);\n\t\tserver.on('error', reject);\n\t});\n\n\t// Prevent Node from waiting for this socket to close before exiting\n\tserver.unref();\n\n\tprocess.on('exit', () => {\n\t\tserver.close();\n\n\t\t/**\n\t\t * Only clean on Unix\n\t\t *\n\t\t * https://nodejs.org/api/net.html#ipc-support:\n\t\t * On Windows, the local domain is implemented using a named pipe.\n\t\t * The path must refer to an entry in \\\\?\\pipe\\ or \\\\.\\pipe\\.\n\t\t * Any characters are permitted, but the latter may do some processing\n\t\t * of pipe names, such as resolving .. sequences. Despite how it might\n\t\t * look, the pipe namespace is flat. Pipes will not persist. They are\n\t\t * removed when the last reference to them is closed. Unlike Unix domain\n\t\t * sockets, Windows will close and remove the pipe when the owning process exits.\n\t\t */\n\t\tif (!isWindows) {\n\t\t\ttry {\n\t\t\t\tfs.rmSync(pipePath);\n\t\t\t} catch {}\n\t\t}\n\t});\n\n\treturn server;\n};\n"
  },
  {
    "path": "src/utils/is-windows.ts",
    "content": "export const isWindows = process.platform === 'win32';\n"
  },
  {
    "path": "src/utils/map-ts-extensions.ts",
    "content": "import path from 'node:path';\nimport { isFilePath, fileUrlPrefix, nodeModulesPath } from './path-utils.js';\n\nconst implicitJsExtensions = ['.js', '.json'];\nconst implicitTsExtensions = ['.ts', '.tsx', '.jsx'];\n\n// Guess extension\nconst localExtensions = [...implicitTsExtensions, ...implicitJsExtensions];\n\n/**\n * If dependency, prioritize .js extensions over .ts\n *\n * .js is more likely to behave correctly than the .ts file\n * https://github.com/evanw/esbuild/releases/tag/v0.20.0\n */\nconst dependencyExtensions = [...implicitJsExtensions, ...implicitTsExtensions];\n\n// Swap extension\nconst tsExtensions: Record<string, string[]> = Object.create(null);\ntsExtensions['.js'] = ['.ts', '.tsx', '.js', '.jsx'];\ntsExtensions['.jsx'] = ['.tsx', '.ts', '.jsx', '.js'];\ntsExtensions['.cjs'] = ['.cts'];\ntsExtensions['.mjs'] = ['.mts'];\n\nexport const mapTsExtensions = (\n\tfilePath: string,\n) => {\n\tconst splitPath = filePath.split('?');\n\tconst pathQuery = splitPath[1] ? `?${splitPath[1]}` : '';\n\tconst [pathname] = splitPath;\n\tconst extension = path.extname(pathname);\n\n\tconst tryPaths: string[] = [];\n\n\tconst tryExtensions = tsExtensions[extension];\n\tif (tryExtensions) {\n\t\tconst extensionlessPath = pathname.slice(0, -extension.length);\n\n\t\ttryPaths.push(\n\t\t\t...tryExtensions.map(\n\t\t\t\textension_ => (\n\t\t\t\t\textensionlessPath\n\t\t\t\t\t+ extension_\n\t\t\t\t\t+ pathQuery\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}\n\n\tconst guessExtensions = (\n\t\t(\n\t\t\t!(filePath.startsWith(fileUrlPrefix) || isFilePath(pathname))\n\t\t\t|| pathname.includes(nodeModulesPath)\n\t\t\t|| pathname.includes('/node_modules/') // For file:// URLs on Windows\n\t\t)\n\t\t\t? dependencyExtensions\n\t\t\t: localExtensions\n\t);\n\ttryPaths.push(\n\t\t...guessExtensions.map(\n\t\t\textension_ => (\n\t\t\t\tpathname\n\t\t\t\t+ extension_\n\t\t\t\t+ pathQuery\n\t\t\t),\n\t\t),\n\t);\n\n\treturn tryPaths;\n};\n"
  },
  {
    "path": "src/utils/node-features.ts",
    "content": "export type Version = [number, number, number];\n\n// Is v1 greater or equal to v2?\nconst isVersionGreaterOrEqual = (v1: Version, v2: Version): boolean => {\n\tconst majorDiff = v1[0] - v2[0];\n\tif (majorDiff === 0) {\n\t\tconst minorDiff = v1[1] - v2[1];\n\t\tif (minorDiff === 0) {\n\t\t\treturn v1[2] >= v2[2];\n\t\t}\n\t\treturn minorDiff > 0;\n\t}\n\treturn majorDiff > 0;\n};\n\nconst currentNodeVersion = process.versions.node.split('.').map(Number) as Version;\n\nexport const isFeatureSupported = (\n\tversions: Version[],\n\tcurrent = currentNodeVersion,\n) => {\n\tfor (let i = 0; i < versions.length; i += 1) {\n\t\tconst version = versions[i];\n\n\t\t// If last version, check if greater\n\t\tif (i === versions.length - 1) {\n\t\t\treturn isVersionGreaterOrEqual(current, version);\n\t\t}\n\n\t\t// Otherwise, check within major range\n\t\tif (current[0] === version[0]) {\n\t\t\treturn isVersionGreaterOrEqual(current, version);\n\t\t}\n\t}\n\n\treturn false;\n};\n\n// https://nodejs.org/docs/latest/api/module.html#moduleregisterspecifier-parenturl-options\nexport const moduleRegister: Version[] = [\n\t[18, 19, 0],\n\t[20, 6, 0],\n];\n\n// https://nodejs.org/docs/latest/api/esm.html#import-attributes\nexport const importAttributes: Version[] = [\n\t[18, 19, 0],\n\t[20, 10, 0],\n\t[21, 0, 0],\n];\n\n// https://github.com/nodejs/node/releases/tag/v21.0.0\nexport const testRunnerGlob: Version[] = [\n\t[21, 0, 0],\n];\n\n// https://github.com/nodejs/node/pull/50825\nexport const esmLoadReadFile: Version[] = [\n\t[20, 11, 0],\n\t[21, 3, 0],\n];\n\n// https://github.com/nodejs/node/pull/55085\nexport const requireEsm: Version[] = [\n\t[20, 19, 0],\n\t[23, 0, 0],\n];\n"
  },
  {
    "path": "src/utils/path-utils.ts",
    "content": "import path from 'node:path';\n\n/**\n * Prior to calling this function, it's expected that Windows paths have been filtered out\n * via path.isAbsolute()\n *\n * Windows paths cannot be correctly parsed (e.g. new URL('C:\\Users\\Example\\file.txt')\n */\nconst getScheme = (url: string) => {\n\tconst schemeIndex = url.indexOf(':');\n\tif (schemeIndex === -1) { return; }\n\treturn url.slice(0, schemeIndex);\n};\n\nexport const isRelativePath = (request: string) => (\n\trequest[0] === '.'\n\t&& (\n\t\trequest[1] === '/'\n\t\t|| (request[1] === '.' || request[2] === '/')\n\t)\n);\n\nexport const isFilePath = (request: string) => (\n\tisRelativePath(request)\n\t|| path.isAbsolute(request)\n);\n\n// In Node, bare specifiers (packages and core modules) do not accept queries\nexport const requestAcceptsQuery = (request: string) => {\n\t// ./foo.js?query\n\t// /foo.js?query in UNIX\n\tif (isFilePath(request)) {\n\t\treturn true;\n\t}\n\n\tconst scheme = getScheme(request);\n\treturn (\n\t\t// Expected to be file, https, etc...\n\t\tscheme\n\n\t\t// node:url maps to a bare-specifier, which does not accept queries\n\t\t// But URLs like file:// or https:// do\n\t\t&& scheme !== 'node'\n\t);\n};\n\nexport const fileUrlPrefix = 'file://';\n\nexport const tsExtensions = ['.ts', '.tsx', '.jsx', '.mts', '.cts'];\n\nexport const tsExtensionsPattern = /\\.([cm]?ts|[tj]sx)($|\\?)/;\n\nexport const cjsExtensionPattern = /[/\\\\].+\\.(?:cts|cjs)(?:$|\\?)/;\n\nexport const isJsonPattern = /\\.json($|\\?)/;\n\nexport const isDirectoryPattern = /\\/(?:$|\\?)/;\n\n// Only matches packages names without subpaths (e.g. `foo` but not `foo/bar`)\n// Back slash included to exclude Windows paths\nexport const isBarePackageNamePattern = /^(?:@[^/]+\\/)?[^/\\\\]+$/;\n\nexport const nodeModulesPath = `${path.sep}node_modules${path.sep}`;\n"
  },
  {
    "path": "src/utils/read-json-file.ts",
    "content": "import fs from 'node:fs';\n\nexport const readJsonFile = <JsonType>(\n\tfilePath: string | URL,\n) => {\n\ttry {\n\t\tconst jsonString = fs.readFileSync(filePath, 'utf8');\n\t\treturn JSON.parse(jsonString) as JsonType;\n\t} catch {}\n};\n"
  },
  {
    "path": "src/utils/sha1.ts",
    "content": "import crypto from 'node:crypto';\n\nexport const sha1 = (data: string) => (\n\tcrypto\n\t\t.createHash('sha1')\n\t\t.update(data)\n\t\t.digest('hex')\n);\n"
  },
  {
    "path": "src/utils/temporary-directory.ts",
    "content": "import path from 'node:path';\nimport os from 'node:os';\n\n/**\n * Cache directory is based on the user's identifier\n * to avoid permission issues when accessed by a different user\n */\nconst { geteuid } = process;\nconst userId = (\n\tgeteuid\n\t\t// For Linux users with virtual users on CI (e.g. Docker)\n\t\t? geteuid()\n\n\t\t// Use username on Windows because it doesn't have id\n\t\t: os.userInfo().username\n);\n\n/**\n * This ensures that the cache directory is unique per user\n * and has the appropriate permissions\n */\nexport const tmpdir = path.join(os.tmpdir(), `tsx-${userId}`);\n"
  },
  {
    "path": "src/utils/transform/apply-transformers.ts",
    "content": "import remapping, { type SourceMap, type SourceMapInput } from '@ampproject/remapping';\n\ntype MaybePromise<T> = T | Promise<T>;\n\ntype TransformerResult = {\n\tcode: string;\n\tmap: SourceMap;\n} | undefined;\n\ntype Transformer<\n\tReturnType extends MaybePromise<TransformerResult>\n> = (\n\tfilePath: string,\n\tcode: string,\n) => ReturnType;\n\nexport type Transformed = {\n\tcode: string;\n\tmap: SourceMap;\n};\n\nexport const applyTransformersSync = (\n\tfilePath: string,\n\tcode: string,\n\ttransformers: Transformer<TransformerResult>[],\n): Transformed => {\n\tconst maps: SourceMap[] = [];\n\tconst result = { code };\n\n\tfor (const transformer of transformers) {\n\t\tconst transformed = transformer(filePath, result.code);\n\n\t\tif (transformed) {\n\t\t\tObject.assign(result, transformed);\n\t\t\tmaps.unshift(transformed.map);\n\t\t}\n\t}\n\n\treturn {\n\t\t...result,\n\t\tmap: remapping(maps as SourceMapInput[], () => null),\n\t};\n};\n\nexport const applyTransformers = async (\n\tfilePath: string,\n\tcode: string,\n\ttransformers: Transformer<MaybePromise<TransformerResult>>[],\n): Promise<Transformed> => {\n\tconst maps: SourceMap[] = [];\n\tconst result = { code };\n\n\tfor (const transformer of transformers) {\n\t\tconst transformed = await transformer(filePath, result.code);\n\n\t\tif (transformed) {\n\t\t\tObject.assign(result, transformed);\n\t\t\tmaps.unshift(transformed.map);\n\t\t}\n\t}\n\n\treturn {\n\t\t...result,\n\t\tmap: remapping(maps as SourceMapInput[], () => null),\n\t};\n};\n"
  },
  {
    "path": "src/utils/transform/cache.ts",
    "content": "import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { readJsonFile } from '../read-json-file.js';\nimport { tmpdir } from '../temporary-directory.js';\nimport type { Transformed } from './apply-transformers.js';\n\nconst noop = () => {};\nconst getTime = () => Math.floor(Date.now() / 1e8);\n\nclass FileCache<ReturnType> extends Map<string, ReturnType> {\n\t/**\n\t * By using tmpdir, the expectation is for the OS to clean any files\n\t * that haven't been read for a while.\n\t *\n\t * macOS - 3 days: https://superuser.com/a/187105\n\t * Linux - https://serverfault.com/a/377349\n\t *\n\t * Note on Windows, temp files are not cleaned up automatically.\n\t * https://superuser.com/a/1599897\n\t */\n\tcacheDirectory = tmpdir;\n\n\t// Maintained so we can remove it on Windows\n\toldCacheDirectory = path.join(os.tmpdir(), 'tsx');\n\n\tcacheFiles: {\n\t\ttime: number;\n\t\tkey: string;\n\t\tfileName: string;\n\t}[];\n\n\tconstructor() {\n\t\tsuper();\n\n\t\t// Handles race condition if multiple tsx instances are running (#22)\n\t\tfs.mkdirSync(this.cacheDirectory, { recursive: true });\n\n\t\tthis.cacheFiles = fs.readdirSync(this.cacheDirectory).map((fileName) => {\n\t\t\tconst [time, key] = fileName.split('-');\n\t\t\treturn {\n\t\t\t\ttime: Number(time),\n\t\t\t\tkey,\n\t\t\t\tfileName,\n\t\t\t};\n\t\t});\n\n\t\tsetImmediate(() => {\n\t\t\tthis.expireDiskCache();\n\t\t\tthis.removeOldCacheDirectory();\n\t\t});\n\t}\n\n\toverride get(key: string) {\n\t\tconst memoryCacheHit = super.get(key);\n\n\t\tif (memoryCacheHit) {\n\t\t\treturn memoryCacheHit;\n\t\t}\n\n\t\tconst diskCacheHit = this.cacheFiles.find(cache => cache.key === key);\n\t\tif (!diskCacheHit) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst cacheFilePath = path.join(this.cacheDirectory, diskCacheHit.fileName);\n\t\tconst cachedResult = readJsonFile<ReturnType>(cacheFilePath);\n\n\t\tif (!cachedResult) {\n\t\t\t// Remove broken cache file\n\t\t\tfs.promises.unlink(cacheFilePath).then(\n\t\t\t\t() => {\n\t\t\t\t\tconst index = this.cacheFiles.indexOf(diskCacheHit);\n\t\t\t\t\tthis.cacheFiles.splice(index, 1);\n\t\t\t\t},\n\n\t\t\t\t() => {},\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Load it into memory\n\t\tsuper.set(key, cachedResult);\n\n\t\treturn cachedResult;\n\t}\n\n\toverride set(key: string, value: ReturnType) {\n\t\tsuper.set(key, value);\n\n\t\tif (value) {\n\t\t\t/**\n\t\t\t * Time is inaccurate by ~27.7 hours to minimize data\n\t\t\t * and because this level of fidelity wont matter\n\t\t\t */\n\t\t\tconst time = getTime();\n\n\t\t\tfs.promises.writeFile(\n\t\t\t\tpath.join(this.cacheDirectory, `${time}-${key}`),\n\t\t\t\tJSON.stringify(value),\n\t\t\t).catch(noop);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\texpireDiskCache() {\n\t\tconst time = getTime();\n\n\t\tfor (const cache of this.cacheFiles) {\n\t\t\t// Remove if older than ~7 days\n\t\t\tif ((time - cache.time) > 7) {\n\t\t\t\tfs.promises.unlink(path.join(this.cacheDirectory, cache.fileName)).catch(noop);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync removeOldCacheDirectory() {\n\t\ttry {\n\t\t\tconst exists = await fs.promises.access(this.oldCacheDirectory).then(() => true);\n\t\t\tif (exists) {\n\t\t\t\tif ('rm' in fs.promises) {\n\t\t\t\t\tawait fs.promises.rm(\n\t\t\t\t\t\tthis.oldCacheDirectory,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trecursive: true,\n\t\t\t\t\t\t\tforce: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tawait fs.promises.rmdir(\n\t\t\t\t\t\tthis.oldCacheDirectory,\n\t\t\t\t\t\t{ recursive: true },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {}\n\t}\n}\n\nexport default (\n\tprocess.env.TSX_DISABLE_CACHE\n\t\t? new Map<string, Transformed>()\n\t\t: new FileCache<Transformed>()\n);\n"
  },
  {
    "path": "src/utils/transform/get-esbuild-options.ts",
    "content": "import path from 'node:path';\nimport type { TransformOptions, TransformResult } from 'esbuild';\nimport type { SourceMap } from '@ampproject/remapping';\n\nexport const baseConfig = Object.freeze({\n\ttarget: `node${process.versions.node}`,\n\n\t// \"default\" tells esbuild to infer loader from file name\n\t// https://github.com/evanw/esbuild/blob/4a07b17adad23e40cbca7d2f8931e8fb81b47c33/internal/bundler/bundler.go#L158\n\tloader: 'default',\n});\n\n// match Node.js debugger flags\n// https://nodejs.org/api/cli.html#--inspecthostport\nconst NODE_DEBUGGER_FLAG_REGEX = /^--inspect(?:-brk|-port|-publish-uid|-wait)?(?:=|$)/;\n\nconst isNodeDebuggerEnabled = process.execArgv.some(flag => NODE_DEBUGGER_FLAG_REGEX.test(flag));\n\nexport const cacheConfig = {\n\t...baseConfig,\n\n\tsourcemap: true,\n\n\t/**\n\t * Improve performance by only generating sourcesContent\n\t * when V8 coverage is enabled or Node.js debugger is enabled\n\t *\n\t * https://esbuild.github.io/api/#sources-content\n\t */\n\tsourcesContent: Boolean(process.env.NODE_V8_COVERAGE) || isNodeDebuggerEnabled,\n\n\t/**\n\t * Smaller output for cache and marginal performance improvement:\n\t * https://twitter.com/evanwallace/status/1396336348366180359?s=20\n\t *\n\t * minifyIdentifiers is disabled because debuggers don't use the\n\t * `names` property from the source map\n\t *\n\t * minifySyntax is disabled because it does some tree-shaking\n\t * eg. unused try-catch error variable\n\t */\n\tminifyWhitespace: true,\n\n\t/**\n\t * esbuild renames variables even if minification is not enabled\n\t * https://esbuild.github.io/try/#dAAwLjE5LjUAAGNvbnN0IGEgPSAxOwooZnVuY3Rpb24gYSgpIHt9KTs\n\t */\n\tkeepNames: true,\n};\n\nexport const patchOptions = (\n\toptions: TransformOptions,\n) => {\n\tconst originalSourcefile = options.sourcefile;\n\n\tif (originalSourcefile) {\n\t\tconst extension = path.extname(originalSourcefile.split('?')[0]);\n\n\t\tif (extension) {\n\t\t\t// https://github.com/evanw/esbuild/issues/1932\n\t\t\tif (extension === '.cts' || extension === '.mts') {\n\t\t\t\toptions.sourcefile = `${originalSourcefile.slice(0, -3)}ts`;\n\t\t\t} else if (extension === '.mjs') { // only used by CJS loader\n\t\t\t\toptions.sourcefile = `${originalSourcefile.slice(0, -3)}js`;\n\t\t\t}\n\t\t} else {\n\t\t\t// esbuild errors to detect loader when a file doesn't have an extension\n\t\t\toptions.sourcefile += '.js';\n\t\t}\n\t}\n\n\treturn (\n\t\tresult: TransformResult,\n\t) => {\n\t\tif (result.map) {\n\t\t\tif (options.sourcefile !== originalSourcefile) {\n\t\t\t\tresult.map = result.map.replace(\n\t\t\t\t\tJSON.stringify(options.sourcefile),\n\t\t\t\t\tJSON.stringify(originalSourcefile),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tresult.map = JSON.parse(result.map);\n\t\t}\n\n\t\treturn result as TransformResult & { map: SourceMap };\n\t};\n};\n"
  },
  {
    "path": "src/utils/transform/index.ts",
    "content": "import { pathToFileURL, fileURLToPath } from 'node:url';\nimport {\n\ttransform as esbuildTransform,\n\ttransformSync as esbuildTransformSync,\n\tversion as esbuildVersion,\n\ttype TransformOptions,\n\ttype TransformFailure,\n} from 'esbuild';\nimport { sha1 } from '../sha1.js';\nimport {\n\tversion as transformDynamicImportVersion,\n\ttransformDynamicImport,\n} from './transform-dynamic-import.js';\nimport cache from './cache.js';\nimport {\n\tapplyTransformersSync,\n\tapplyTransformers,\n\ttype Transformed,\n} from './apply-transformers.js';\nimport {\n\tcacheConfig,\n\tpatchOptions,\n} from './get-esbuild-options.js';\n\nconst formatEsbuildError = (\n\terror: TransformFailure,\n) => {\n\terror.name = 'TransformError';\n\t// @ts-expect-error deleting non-option property\n\tdelete error.errors;\n\t// @ts-expect-error deleting non-option property\n\tdelete error.warnings;\n\tthrow error;\n};\n\n// Used by cjs-loader\nexport const transformSync = (\n\tcode: string,\n\tfilePathOrUrl: string,\n\textendOptions?: TransformOptions,\n): Transformed => {\n\tconst define: { [key: string]: string } = {};\n\n\tlet url: string;\n\tlet filePath: string;\n\tlet query: string | undefined;\n\n\tif (filePathOrUrl.startsWith('file://')) {\n\t\turl = filePathOrUrl;\n\t\tconst parsed = new URL(filePathOrUrl);\n\t\tfilePath = fileURLToPath(parsed);\n\t} else {\n\t\t[filePath, query] = filePathOrUrl.split('?');\n\t\turl = pathToFileURL(filePath) + (query ? `?${query}` : '');\n\t}\n\n\tif (\n\t\t!(\n\t\t\tfilePath.endsWith('.cjs')\n\t\t\t|| filePath.endsWith('.cts')\n\t\t)\n\t) {\n\t\tdefine['import.meta.url'] = JSON.stringify(url);\n\t}\n\n\tconst esbuildOptions = {\n\t\t...cacheConfig,\n\t\tformat: 'cjs',\n\t\tsourcefile: filePath,\n\t\tdefine,\n\t\tbanner: `__filename=${JSON.stringify(filePath)};(()=>{`,\n\t\tfooter: '})()',\n\n\t\t// CJS Annotations for Node. Used by ESM loader for CJS interop\n\t\tplatform: 'node',\n\n\t\t...extendOptions,\n\t} as const;\n\n\tconst hash = sha1([\n\t\tcode,\n\t\tJSON.stringify(esbuildOptions),\n\t\tesbuildVersion,\n\t\ttransformDynamicImportVersion,\n\t].join('-'));\n\tlet transformed = cache.get(hash);\n\n\tif (!transformed) {\n\t\ttransformed = applyTransformersSync(\n\t\t\tfilePathOrUrl,\n\t\t\tcode,\n\t\t\t[\n\t\t\t\t(_filePath, _code) => {\n\t\t\t\t\tconst patchResult = patchOptions(esbuildOptions);\n\t\t\t\t\tlet result;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = esbuildTransformSync(_code, esbuildOptions);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow formatEsbuildError(error as TransformFailure);\n\t\t\t\t\t}\n\t\t\t\t\treturn patchResult(result);\n\t\t\t\t},\n\t\t\t\t(_filePath, _code) => transformDynamicImport(_filePath, _code, true),\n\t\t\t],\n\t\t);\n\n\t\tcache.set(hash, transformed);\n\t}\n\n\treturn transformed;\n};\n\n// Used by esm-loader\nexport const transform = async (\n\tcode: string,\n\tfilePath: string,\n\textendOptions?: TransformOptions,\n): Promise<Transformed> => {\n\tconst esbuildOptions = {\n\t\t...cacheConfig,\n\t\tformat: 'esm',\n\t\tsourcefile: filePath,\n\t\t...extendOptions,\n\t} as const;\n\n\tconst hash = sha1([\n\t\tcode,\n\t\tJSON.stringify(esbuildOptions),\n\t\tesbuildVersion,\n\t\ttransformDynamicImportVersion,\n\t].join('-'));\n\tlet transformed = cache.get(hash);\n\n\tif (!transformed) {\n\t\ttransformed = await applyTransformers(\n\t\t\tfilePath,\n\t\t\tcode,\n\t\t\t[\n\t\t\t\tasync (_filePath, _code) => {\n\t\t\t\t\tconst patchResult = patchOptions(esbuildOptions);\n\t\t\t\t\tlet result;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = await esbuildTransform(_code, esbuildOptions);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow formatEsbuildError(error as TransformFailure);\n\t\t\t\t\t}\n\t\t\t\t\treturn patchResult(result);\n\t\t\t\t},\n\t\t\t\t(_filePath, _code) => transformDynamicImport(_filePath, _code, true),\n\t\t\t],\n\t\t);\n\n\t\tcache.set(hash, transformed);\n\t}\n\n\treturn transformed;\n};\n"
  },
  {
    "path": "src/utils/transform/transform-dynamic-import.ts",
    "content": "import MagicString from 'magic-string';\nimport type { SourceMap } from '@ampproject/remapping';\nimport { parseEsm } from '../es-module-lexer.js';\n\nexport const version = '2';\n\nconst toEsmFunctionString = ((imported: Record<string, unknown>) => {\n\tconst d = 'default';\n\tif (\n\t\timported[d]\n\t\t&& typeof imported[d] === 'object'\n\t\t&& '__esModule' in imported[d]\n\t) {\n\t\treturn imported[d];\n\t}\n\n\treturn imported;\n}).toString();\n\nconst handleDynamicImport = `.then(${toEsmFunctionString})`;\n\nexport const transformDynamicImport = (\n\tfilePath: string,\n\tcode: string,\n\tisMinified?: boolean,\n) => {\n\t// Naive check (regex is too slow)\n\tif (isMinified) {\n\t\t// If minified, we can safely check for \"import(\" to avoid parsing\n\t\tif (!code.includes('import(')) {\n\t\t\treturn;\n\t\t}\n\t} else if (!code.includes('import')) {\n\t\t// This is a bit more expensive as we end up parsing even if import statements are detected\n\t\treturn;\n\t}\n\n\t// Passing in the filePath improves Parsing Error message\n\tconst parsed = parseEsm(code, filePath);\n\tconst dynamicImports = parsed[0].filter(maybeDynamic => maybeDynamic.d > -1);\n\tif (dynamicImports.length === 0) {\n\t\treturn;\n\t}\n\n\tconst magicString = new MagicString(code);\n\n\tfor (const dynamicImport of dynamicImports) {\n\t\tmagicString.appendRight(dynamicImport.se, handleDynamicImport);\n\t}\n\n\tconst newCode = magicString.toString();\n\tconst newMap = magicString.generateMap({\n\t\tsource: filePath,\n\t\tincludeContent: false,\n\n\t\t/**\n\t\t * The performance hit on this is very high\n\t\t * Since we're only transforming import()s, I think this may be overkill\n\t\t */\n\t\thires: 'boundary',\n\t}) as unknown as SourceMap;\n\n\treturn {\n\t\tcode: newCode,\n\t\tmap: newMap,\n\t};\n};\n"
  },
  {
    "path": "src/utils/tsconfig.ts",
    "content": "import path from 'node:path';\nimport {\n\tgetTsconfig,\n\tparseTsconfig,\n\tcreateFilesMatcher,\n\tcreatePathsMatcher,\n\ttype TsConfigResult,\n\ttype FileMatcher,\n} from 'get-tsconfig';\n\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let fileMatcher: undefined | FileMatcher;\n\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let tsconfigPathsMatcher: undefined | ReturnType<typeof createPathsMatcher>;\n\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let allowJs = false;\n\nexport const loadTsconfig = (\n\tconfigPath?: string,\n) => {\n\tlet tsconfig: TsConfigResult | null = null;\n\tif (configPath) {\n\t\tconst resolvedConfigPath = path.resolve(configPath);\n\t\ttsconfig = {\n\t\t\tpath: resolvedConfigPath,\n\t\t\tconfig: parseTsconfig(resolvedConfigPath),\n\t\t};\n\t} else {\n\t\ttry {\n\t\t\ttsconfig = getTsconfig();\n\t\t} catch {\n\t\t\t// Not warning here for now because it gets warned twice\n\t\t\t// Once by ESM loader and then by CJS loader\n\t\t\t// const disableWarning = (\n\t\t\t// \tgetFlag('--no-warnings', Boolean)\n\t\t\t// \t|| Boolean(process.env.NODE_NO_WARNINGS)\n\t\t\t// );\n\t\t\t// if (!disableWarning) {\n\t\t\t// \tif (error instanceof Error) {\n\t\t\t// \t\tconsole.warn(`(tsx:${process.pid}) [-----] TsconfigWarning:`, error.message);\n\t\t\t// \t}\n\t\t\t// }\n\t\t}\n\n\t\tif (!tsconfig) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tfileMatcher = createFilesMatcher(tsconfig);\n\ttsconfigPathsMatcher = createPathsMatcher(tsconfig);\n\tallowJs = tsconfig?.config.compilerOptions?.allowJs ?? false;\n};\n"
  },
  {
    "path": "src/utils/url-search-params-stringify.ts",
    "content": "export const urlSearchParamsStringify = (\n\tsearchParams: URLSearchParams,\n) => {\n\t// URLSearchParams#size not implemented in Node 18.0.0\n\tconst size = Array.from(searchParams).length;\n\treturn size > 0 ? `?${searchParams.toString()}` : '';\n};\n"
  },
  {
    "path": "src/watch/index.ts",
    "content": "import type { ChildProcess } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { constants as osConstants } from 'node:os';\nimport path from 'node:path';\nimport { command } from 'cleye';\nimport { watch } from 'chokidar';\nimport { lightMagenta, lightGreen, yellow } from 'kolorist';\nimport { run } from '../run.js';\nimport {\n\tremoveArgvFlags,\n\tignoreAfterArgument,\n} from '../remove-argv-flags.js';\nimport { createIpcServer } from '../utils/ipc/server.js';\nimport {\n\tclearScreen,\n\tdebounce,\n\tlog,\n} from './utils.js';\n\nconst flags = {\n\tnoCache: {\n\t\ttype: Boolean,\n\t\tdescription: 'Disable caching',\n\t\tdefault: false,\n\t},\n\ttsconfig: {\n\t\ttype: String,\n\t\tdescription: 'Custom tsconfig.json path',\n\t},\n\tclearScreen: {\n\t\ttype: Boolean,\n\t\tdescription: 'Clearing the screen on rerun',\n\t\tdefault: true,\n\t},\n\t// Deprecated\n\tignore: {\n\t\ttype: [String],\n\t\tdescription: 'Paths & globs to exclude from being watched (Deprecated: use --exclude)',\n\t},\n\tinclude: {\n\t\ttype: [String],\n\t\tdescription: 'Additional paths & globs to watch',\n\t},\n\texclude: {\n\t\ttype: [String],\n\t\tdescription: 'Paths & globs to exclude from being watched',\n\t},\n} as const;\n\nexport const watchCommand = command({\n\tname: 'watch',\n\tparameters: ['<script path>'],\n\tflags,\n\thelp: {\n\t\tdescription: 'Run the script and watch for changes',\n\t},\n\n\t/**\n\t * ignoreAfterArgument needs to parse the first argument\n\t * because cleye will error on missing arguments\n\t *\n\t * Remove once cleye supports error callbacks on missing arguments\n\t */\n\tignoreArgv: ignoreAfterArgument(false),\n}, async (argv) => {\n\tconst rawArgvs = removeArgvFlags(flags, process.argv.slice(3));\n\tconst options = {\n\t\tnoCache: argv.flags.noCache,\n\t\ttsconfigPath: argv.flags.tsconfig,\n\t\tclearScreen: argv.flags.clearScreen,\n\t\tinclude: argv.flags.include,\n\t\texclude: [\n\t\t\t...argv.flags.ignore,\n\t\t\t...argv.flags.exclude,\n\t\t],\n\t\tipc: true,\n\t};\n\n\tlet runProcess: ChildProcess | undefined;\n\tlet exiting = false;\n\n\tconst server = await createIpcServer();\n\n\tserver.on('data', (data) => {\n\t\t// Collect run-time dependencies to watch\n\t\tif (\n\t\t\tdata\n\t\t\t&& typeof data === 'object'\n\t\t\t&& 'type' in data\n\t\t\t&& data.type === 'dependency'\n\t\t\t&& 'path' in data\n\t\t\t&& typeof data.path === 'string'\n\t\t) {\n\t\t\tconst dependencyPath = (\n\t\t\t\tdata.path.startsWith('file:')\n\t\t\t\t\t? fileURLToPath(data.path)\n\t\t\t\t\t: data.path\n\t\t\t);\n\n\t\t\tif (path.isAbsolute(dependencyPath)) {\n\t\t\t\twatcher.add(dependencyPath);\n\t\t\t}\n\t\t}\n\t});\n\n\tconst spawnProcess = () => {\n\t\tif (exiting) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn run(rawArgvs, options);\n\t};\n\n\tlet waitingChildExit = false;\n\n\tconst killProcess = async (\n\t\tchildProcess: ChildProcess,\n\t\tsignal: NodeJS.Signals = 'SIGTERM',\n\t\tforceKillOnTimeout = 5000,\n\t) => {\n\t\tlet exited = false;\n\t\tconst waitForExit = new Promise<number | null>((resolve) => {\n\t\t\tchildProcess.on('exit', (exitCode) => {\n\t\t\t\texited = true;\n\t\t\t\twaitingChildExit = false;\n\t\t\t\tresolve(exitCode);\n\t\t\t});\n\t\t});\n\n\t\twaitingChildExit = true;\n\t\tchildProcess.kill(signal);\n\n\t\tsetTimeout(() => {\n\t\t\tif (!exited) {\n\t\t\t\tlog(yellow(`Process didn't exit in ${Math.floor(forceKillOnTimeout / 1000)}s. Force killing...`));\n\t\t\t\tchildProcess.kill('SIGKILL');\n\t\t\t}\n\t\t}, forceKillOnTimeout);\n\n\t\treturn await waitForExit;\n\t};\n\n\tconst reRun = debounce(async (event?: string, filePath?: string) => {\n\t\tconst reason = event ? `${event ? lightMagenta(event) : ''}${filePath ? ` in ${lightGreen(`./${filePath}`)}` : ''}` : '';\n\n\t\tif (waitingChildExit) {\n\t\t\tlog(reason, yellow('Process hasn\\'t exited. Killing process...'));\n\t\t\trunProcess!.kill('SIGKILL');\n\t\t\treturn;\n\t\t}\n\n\t\t// If not first run\n\t\tif (runProcess) {\n\t\t\t// If process still running\n\t\t\tif (runProcess.exitCode === null) {\n\t\t\t\tlog(reason, yellow('Restarting...'));\n\t\t\t\tawait killProcess(runProcess);\n\t\t\t} else {\n\t\t\t\tlog(reason, yellow('Rerunning...'));\n\t\t\t}\n\n\t\t\tif (options.clearScreen) {\n\t\t\t\tprocess.stdout.write(clearScreen);\n\t\t\t}\n\t\t}\n\n\t\trunProcess = spawnProcess();\n\t}, 100);\n\n\treRun();\n\n\tconst relaySignal = (signal: NodeJS.Signals) => {\n\t\t// Disable further spawns\n\t\texiting = true;\n\n\t\t// Child is still running, kill it\n\t\tif (runProcess?.exitCode === null) {\n\t\t\tif (waitingChildExit) {\n\t\t\t\tlog(yellow('Previous process hasn\\'t exited yet. Force killing...'));\n\t\t\t}\n\n\t\t\tkillProcess(\n\t\t\t\trunProcess,\n\t\t\t\t// Second Ctrl+C force kills\n\t\t\t\twaitingChildExit ? 'SIGKILL' : signal,\n\t\t\t).then(\n\t\t\t\t(exitCode) => {\n\t\t\t\t\t// eslint-disable-next-line n/no-process-exit\n\t\t\t\t\tprocess.exit(exitCode ?? 0);\n\t\t\t\t},\n\t\t\t\t() => {},\n\t\t\t);\n\t\t} else {\n\t\t\t// eslint-disable-next-line n/no-process-exit\n\t\t\tprocess.exit(osConstants.signals[signal]);\n\t\t}\n\t};\n\n\tprocess.on('SIGINT', relaySignal);\n\tprocess.on('SIGTERM', relaySignal);\n\n\t/**\n\t * Ideally, we can get a list of files loaded from the run above\n\t * and only watch those files, but it's not possible to detect\n\t * the full dependency-tree at run-time because they can be hidden\n\t * in a if-condition/async-delay.\n\t *\n\t * As an alternative, we watch cwd and all run-time dependencies\n\t */\n\tconst watcher = watch(\n\t\t[\n\t\t\t...argv._,\n\t\t\t...options.include,\n\t\t],\n\t\t{\n\t\t\tcwd: process.cwd(),\n\t\t\tignoreInitial: true,\n\t\t\tignored: [\n\t\t\t\t// Hidden directories like .git\n\t\t\t\t'**/.*/**',\n\n\t\t\t\t// Hidden files (e.g. logs or temp files)\n\t\t\t\t'**/.*',\n\n\t\t\t\t// 3rd party packages\n\t\t\t\t'**/{node_modules,bower_components,vendor}/**',\n\n\t\t\t\t...options.exclude,\n\t\t\t],\n\t\t\tignorePermissionErrors: true,\n\t\t},\n\t).on('all', reRun);\n\n\t// On \"Return\" key\n\tprocess.stdin.on('data', () => reRun('Return key'));\n});\n"
  },
  {
    "path": "src/watch/utils.ts",
    "content": "import { gray, lightCyan } from 'kolorist';\n\nconst currentTime = () => (new Date()).toLocaleTimeString();\n\nexport const log = (...messages: unknown[]) => console.log(\n\tgray(currentTime()),\n\tlightCyan('[tsx]'),\n\t...messages,\n);\n\n// From ansi-escapes\n// https://github.com/sindresorhus/ansi-escapes/blob/2b3b59c56ff77a/index.js#L80\nexport const clearScreen = '\\u001Bc';\n\nexport const debounce = <T extends (this: unknown, ...args: any[]) => void>(\n\toriginalFunction: T,\n\tduration: number,\n): T => {\n\tlet timeout: NodeJS.Timeout | undefined;\n\n\treturn function () {\n\t\tif (timeout) {\n\t\t\tclearTimeout(timeout);\n\t\t}\n\n\t\ttimeout = setTimeout(\n\t\t\t() => Reflect.apply(originalFunction, this, arguments),\n\t\t\tduration,\n\t\t);\n\t} as T;\n};\n"
  },
  {
    "path": "tests/fixtures.ts",
    "content": "import outdent from 'outdent';\nimport type { PackageJson, TsConfigJson } from 'type-fest';\n\nexport const createPackageJson = (packageJson: PackageJson) => JSON.stringify(packageJson);\n\nexport const createTsconfig = (tsconfig: TsConfigJson) => JSON.stringify(tsconfig);\n\nconst cjsContextCheck = 'typeof module !== \\'undefined\\'';\nconst tsCheck = '1 as number';\n\nconst declareReact = `\nconst React = {\n\tcreateElement: (...args) => Array.from(args),\n};\n`;\n\nexport const jsxCheck = '<><div>JSX</div></>';\n\nconst preserveName = `\nassert(\n\t(function functionName() {}).name === 'functionName',\n\t'Name should be preserved'\n);\n`;\n\nconst syntaxLowering = `\n// es2016 - Exponentiation operator\n10 ** 4;\n\n// es2017 - Async functions\n(async () => {});\n\n// es2018 - Spread properties\n({...Object});\n\n// es2018 - Rest properties\nconst {...x} = Object;\n\n// es2019 - Optional catch binding\ntry {} catch {}\n\n// es2020 - Optional chaining\nObject?.keys;\n\n// es2020 - Nullish coalescing\nObject ?? true\n\n// es2020 - import.meta\n// import.meta\n\n// es2021 - Logical assignment operators\n// let a = false; a ??= true; a ||= true; a &&= true;\n\n// es2022 - Class instance fields\n(class { x });\n\n// es2022 - Static class fields\n(class { static x });\n\n// es2022 - Private instance methods\n(class { #x() {} });\n\n// es2022 - Private instance fields\n(class { #x });\n\n// es2022 - Private static methods\n(class { static #x() {} });\n\n// es2022 - Private static fields\n(class { static #x });\n\n// es2022 - Class static blocks\n(class { static {} });\n\nexport const named = 2;\nexport default 1;\n`;\n\nconst sourcemap = {\n\t// Adding the dynamic import helps test the import transformation's source map\n\ttest: (\n\t\textension: string,\n\t) => `import ('node:fs');\\nconst { stack } = new Error(); const searchString = 'index.${extension}:SOURCEMAP_LINE'; assert(stack.includes(searchString), \\`Expected \\${searchString} in stack: \\${stack}\\`)`,\n\ttag: (\n\t\tstrings: TemplateStringsArray,\n\t\t...values: string[]\n\t) => {\n\t\tconst finalString = String.raw({ raw: strings }, ...values);\n\t\tconst lineNumber = finalString.split('\\n').findIndex(line => line.includes('SOURCEMAP_LINE')) + 1;\n\t\treturn finalString.replaceAll('SOURCEMAP_LINE', lineNumber.toString());\n\t},\n};\n\nexport const expectErrors = {\n\t'node_modules/expect-errors/index.js': `\n\texports.expectErrors = async (...assertions) => {\n\t\tlet errors = await Promise.all(\n\t\t\tassertions.map(async ([fn, expectedError]) => {\n\t\t\t\tlet thrown;\n\t\t\t\ttry {\n\t\t\t\t\tawait fn();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrown = error;\n\t\t\t\t}\n\n\t\t\t\tif (!thrown) {\n\t\t\t\t\treturn new Error('No error thrown');\n\t\t\t\t} else if (\n\t\t\t\t\t!thrown.message.includes(expectedError)\n\t\t\t\t\t&& !thrown.stack.includes(expectedError)\n\t\t\t\t) {\n\t\t\t\t\treturn new Error(\\`Message \\${JSON.stringify(expectedError)} not found in \\${JSON.stringify(thrown.message)}\\n\\${thrown.stack}\\`);\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\n\t\terrors = errors.filter(Boolean);\n\n\t\tif (errors.length > 0) {\n\t\t\tconsole.error(errors);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t};\n\t`,\n};\n\nexport const files = {\n\t...expectErrors,\n\n\t'js/index.js': outdent`\n\timport assert from 'assert';\n\tconsole.log(JSON.stringify({\n\t\timportMetaUrl: import.meta.url,\n\t\t__filename: typeof __filename !== 'undefined' ? __filename : undefined,\n\t}));\n\t${syntaxLowering}\n\t${preserveName}\n\texport const cjsContext = ${cjsContextCheck};\n\n\t// Implicit directory import works outside of immedaite CWD child\n\timport '../json/'\n\t`,\n\n\t'json/index.json': JSON.stringify({ 'loaded-file': 'json' }),\n\n\t'cjs/index.cjs': sourcemap.tag`\n\tconst assert = require('node:assert');\n\tassert(${cjsContextCheck}, 'Should have CJS context');\n\t${preserveName}\n\t${sourcemap.test('cjs')}\n\n\t// Assert __esModule is unwrapped\n\timport ('../ts/index.ts').then((m) => assert(\n\t\t!(typeof m.default === 'object' && ('default' in m.default)),\n\t));\n\texports.named = 'named';\n\n\t// https://github.com/privatenumber/tsx/issues/248\n\tprocess.setUncaughtExceptionCaptureCallback(console.error);\n\t`,\n\n\tmjs: {\n\t\t'index.mjs': outdent`\n\t\timport assert from 'assert';\n\t\timport value from './value.mjs';\n\t\texport const mjsHasCjsContext = ${cjsContextCheck};\n\n\t\tassert(value === 1, 'wrong default export');\n\n\t\timport ('pkg-commonjs').then((m) => assert(\n\t\t\t!(typeof m.default === 'object' && ('default' in m.default)),\n\t\t));\n\t\t`,\n\t\t'value.mjs': 'export default 1',\n\t},\n\n\tts: {\n\t\t'index.ts': sourcemap.tag`\n\t\timport assert from 'assert';\n\t\timport type {Type} from 'resolved-by-tsc'\n\n\t\tinterface Foo {}\n\n\t\ttype Foo = number\n\n\t\tdeclare module 'foo' {}\n\n\t\tenum BasicEnum {\n\t\t\tLeft,\n\t\t\tRight,\n\t\t}\n\n\t\tenum NamedEnum {\n\t\t\tSomeEnum = 'some-value',\n\t\t}\n\n\t\texport const a = BasicEnum.Left;\n\n\t\texport const b = NamedEnum.SomeEnum;\n\n\t\texport default function foo(): string {\n\t\t\treturn 'foo'\n\t\t}\n\n\t\t// For \"ts as tsx\" test\n\t\tconst bar = <T>(value: T) => fn<T>();\n\n\t\t${preserveName}\n\t\t${sourcemap.test('ts')}\n\t\texport const cjsContext = ${cjsContextCheck};\n\t\t${tsCheck};\n\t\t`,\n\n\t\t'period.in.name.ts': 'export { a } from \".\"',\n\t\tdotdot: {\n\t\t\t'index.ts': 'export { a } from \"..\"',\n\t\t\t'dotdot/index.ts': 'export { a } from \"../..\"',\n\t\t},\n\n\t\t'index.js': 'throw new Error(\"should not be loaded\")',\n\t},\n\n\t// TODO: test resolution priority for files 'index.tsx` & 'index.tsx.ts` via 'index.tsx'\n\n\t'jsx/index.jsx': sourcemap.tag`\n\timport assert from 'assert';\n\texport const cjsContext = ${cjsContextCheck};\n\t${declareReact}\n\texport const jsx = ${jsxCheck};\n\t${preserveName}\n\t${sourcemap.test('jsx')}\n\t`,\n\n\t'tsx/index.tsx': sourcemap.tag`\n\timport assert from 'assert';\n\texport const cjsContext = ${cjsContextCheck};\n\t${tsCheck};\n\t${declareReact}\n\texport const jsx = ${jsxCheck};\n\t${preserveName}\n\t${sourcemap.test('tsx')}\n\t`,\n\n\t'mts/index.mts': sourcemap.tag`\n\timport assert from 'assert';\n\texport const mjsHasCjsContext = ${cjsContextCheck};\n\t${tsCheck};\n\t${preserveName}\n\t${sourcemap.test('mts')}\n\t`,\n\n\t'cts/index.cts': sourcemap.tag`\n\tconst assert = require('assert');\n\tassert(${cjsContextCheck}, 'Should have CJS context');\n\t${tsCheck};\n\t${preserveName}\n\t${sourcemap.test('cts')}\n\t`,\n\n\t'tsconfig.json': createTsconfig({\n\t\tcompilerOptions: {\n\t\t\tpaths: {\n\t\t\t\t'@/*': ['./*'],\n\t\t\t},\n\t\t},\n\t}),\n\n\t'file.txt': 'hello',\n\n\t'broken-syntax.ts': 'if',\n\n\t'file-with-sourcemap.js': outdent`\n\tthrow new Error;\n\t//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiYXNkZi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbnRocm93IG5ldyBFcnJvcigpIl0sCiAgIm1hcHBpbmdzIjogIkFBNkJBLE1BQU0sSUFBSSIsCiAgIm5hbWVzIjogW10KfQo=\n\t`,\n\n\tnode_modules: {\n\t\t'pkg-commonjs': {\n\t\t\t'package.json': createPackageJson({\n\t\t\t\ttype: 'commonjs',\n\t\t\t\tmain: './index.js',\n\t\t\t}),\n\t\t\t'index.ts': 'throw new Error(\"should prefer .js over .ts in node_modules\")',\n\t\t\t'index.js': `\n\t\t\t// https://github.com/privatenumber/tsx/issues/726\n\t\t\tif (!require.cache) {\n\t\t\t\tthrow new Error('require.cache should be defined');\n\t\t\t}\n\t\t\t${syntaxLowering}\n\t\t\t`,\n\t\t\t'ts.ts': syntaxLowering,\n\t\t\t'cjs.js': `\n\t\t\tconst _ = exports;\n\t\t\tconst cjsJs = true;\n\t\t\t_.cjsJs = cjsJs;\n\n\t\t\t// Annotate CommonJS exports for Node\n\t\t\t0 && (module.exports = {\n\t\t\t\tcjsJs,\n\t\t\t});\n\t\t\t`,\n\t\t},\n\t\t'pkg-module': {\n\t\t\t'package.json': createPackageJson({\n\t\t\t\ttype: 'module',\n\t\t\t\tmain: './index.js',\n\t\t\t\timports: {\n\t\t\t\t\t'#*': './*',\n\t\t\t\t},\n\t\t\t}),\n\t\t\t'index.ts': 'throw new Error(\"should prefer .js over .ts in node_modules\")',\n\t\t\t'index.js': `${syntaxLowering}\\nexport * from \"./empty-export\"`,\n\t\t\t'empty-export/index.js': 'export {}',\n\t\t\t'ts.ts': `${syntaxLowering}\\nexport * from \"#empty.js\"`,\n\t\t\t'empty.ts': 'export {}',\n\t\t},\n\t\t'pkg-main': {\n\t\t\t'package.json': createPackageJson({\n\t\t\t\tmain: './index.js',\n\t\t\t}),\n\t\t\t'index.ts': syntaxLowering,\n\t\t},\n\t\t'pkg-exports': {\n\t\t\t'package.json': createPackageJson({\n\t\t\t\texports: {\n\t\t\t\t\t'.': './index.js',\n\t\t\t\t\t'./file': './file.js',\n\t\t\t\t\t'./file.js': './error.js',\n\t\t\t\t\t'./file.ts': './error.js',\n\t\t\t\t},\n\t\t\t}),\n\t\t\t'index.ts': syntaxLowering,\n\t\t\t'file.js': syntaxLowering,\n\t\t\t'error.js': 'throw new Error(\"should not be loaded\")',\n\t\t},\n\t},\n};\n"
  },
  {
    "path": "tests/index.ts",
    "content": "import { describe } from 'manten';\nimport { createNode } from './utils/tsx';\nimport { nodeVersions } from './utils/node-versions';\n\n(async () => {\n\tawait describe('tsx', async ({ runTestSuite, describe }) => {\n\t\tawait runTestSuite(import('./specs/repl'));\n\t\tawait runTestSuite(import('./specs/transform'));\n\n\t\tfor (const nodeVersion of nodeVersions) {\n\t\t\tconst node = await createNode(nodeVersion);\n\t\t\tawait describe(`Node ${node.version}`, async ({ runTestSuite }) => {\n\t\t\t\tawait runTestSuite(import('./specs/smoke'), node);\n\t\t\t\tawait runTestSuite(import('./specs/api'), node);\n\t\t\t\tawait runTestSuite(import('./specs/cli'), node);\n\t\t\t\tawait runTestSuite(import('./specs/watch'), node);\n\t\t\t\tawait runTestSuite(import('./specs/loaders'), node);\n\t\t\t\tawait runTestSuite(import('./specs/tsconfig'), node);\n\t\t\t});\n\t\t}\n\t});\n})();\n"
  },
  {
    "path": "tests/specs/api.ts",
    "content": "import path from 'node:path';\nimport { execaNode } from 'execa';\nimport { testSuite, expect } from 'manten';\nimport { createFixture } from 'fs-fixture';\nimport { outdent } from 'outdent';\nimport {\n\ttsxCjsPath,\n\ttsxCjsApiPath,\n\ttsxEsmPath,\n\ttsxEsmApiPath,\n\ttsxEsmApiCjsPath,\n\ttype NodeApis,\n} from '../utils/tsx.js';\nimport { createPackageJson, createTsconfig, expectErrors } from '../fixtures.js';\n\nconst tsFiles = {\n\t'file.ts': outdent`\n\timport { foo } from './foo'\n\timport { json } from './json.json'\n\texport const message = \\`\\${foo} \\${json} \\${(typeof __filename === 'undefined' ? import.meta.url : __filename).split(/[\\\\\\\\/]/).pop()}\\` as string\n\texport { async } from './foo'\n\t`,\n\t'file1.ts': outdent`\n\timport { foo } from './foo?1'\n\timport { json } from './json.json?1'\n\texport const message = \\`\\${foo} \\${json} \\${(typeof __filename === 'undefined' ? import.meta.url : __filename).split(/[\\\\\\\\/]/).pop()}\\` as string\n\texport { async } from './foo?1'\n\t`,\n\t'foo.ts': outdent`\n\timport { setTimeout } from 'node:timers/promises'\n\timport { bar } from './bar.js'\n\tenum Foo {\n\t\tFoo = 'foo',\n\t}\n\texport const foo = \\`\\${Foo.Foo} \\${bar}\\` as string\n\texport const async = setTimeout(10).then(() => require('./async')).catch((error) => error);\n\t`,\n\n\tcjs: {\n\t\tnode_modules: {\n\t\t\t'pkg/index.js': 'module.exports = 1',\n\t\t},\n\t\t'exports-no.cts': outdent`\n\t\t// Supports decorators\n\t\tconst log = (target, key, descriptor) => descriptor;\n\t\tclass Example {\n\t\t\t@log\n\t\t\tgreet() {}\n\t\t}\n\t\tconsole.log(\"cts loaded\" as string)\n\t\t`,\n\t\t'exports-yes.cts': 'module.exports = require(\"./reexport.cjs\") as string; require(\"pkg\");',\n\t\t'esm-syntax.js': 'export const esmSyntax = \"esm syntax\"',\n\t\t'reexport.cjs': outdent`\n\t\texports.cjsReexport = \"cjsReexport\";\n\t\texports.esmSyntax = require(\"./esm-syntax.js\").esmSyntax;\n\t\t`,\n\t},\n\n\t'bar.ts': 'export type A = 1; export { bar } from \"pkg\"',\n\t'async.ts': 'export default \"async\"',\n\t'json.json': JSON.stringify({ json: 'json' }),\n\tnode_modules: {\n\t\tpkg: {\n\t\t\t'package.json': createPackageJson({\n\t\t\t\tname: 'pkg',\n\t\t\t\ttype: 'module',\n\t\t\t\texports: './pkg.js',\n\t\t\t}),\n\t\t\t'pkg.js': 'import \"node:process\"; export const bar = \"bar\";',\n\t\t},\n\t\t'@a/b.cjs': {\n\t\t\t'package.json': createPackageJson({\n\t\t\t\tname: '@a/b.cjs',\n\t\t\t\ttype: 'module',\n\t\t\t\texports: './pkg.js',\n\t\t\t}),\n\t\t\t'pkg.js': 'import \"node:process\"; export const bar = \"bar\";',\n\t\t},\n\t},\n\t'tsconfig.json': createTsconfig({\n\t\tcompilerOptions: {\n\t\t\texperimentalDecorators: true,\n\t\t},\n\t}),\n\t...expectErrors,\n};\n\nexport default testSuite(({ describe }, node: NodeApis) => {\n\tdescribe('API', ({ describe }) => {\n\t\tdescribe('CommonJS', ({ describe, test }) => {\n\t\t\ttest('cli', async () => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'index.ts': outdent`\n\t\t\t\t\timport { message } from './file';\n\n\t\t\t\t\tconsole.log(message, new Error().stack);\n\t\t\t\t\t`,\n\t\t\t\t\t...tsFiles,\n\t\t\t\t});\n\n\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('index.ts'), {\n\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\tnodeOptions: ['--require', tsxCjsPath],\n\t\t\t\t});\n\t\t\t\texpect(stdout).toContain('foo bar');\n\t\t\t\texpect(stdout).toContain('index.ts:3:22');\n\t\t\t});\n\n\t\t\ttest('loader overwritable from Module', async () => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'index.mjs': outdent`\n\t\t\t\t\timport Module from 'node:module';\n\t\t\t\t\tconst _require = Module.createRequire(import.meta.url);\n\t\t\t\t\t_require.extensions['.ts'] = () => {};\n\t\t\t\t\t`,\n\t\t\t\t});\n\n\t\t\t\tawait execaNode(fixture.getPath('index.mjs'), {\n\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\tnodeOptions: ['--require', tsxCjsPath],\n\t\t\t\t});\n\t\t\t});\n\n\t\t\ttest('works with append-transform (nyc)', async () => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'index.js': outdent`\n\t\t\t\t\timport path from 'node:path';\n\t\t\t\t\timport './ts.ts'\n\t\t\t\t\t`,\n\t\t\t\t\t'ts.ts': 'export const ts = \"ts\" as string',\n\t\t\t\t\t'hook.js': outdent`\n\t\t\t\t\tconst path = require('path');\n\t\t\t\t\tconst appendTransform = require('append-transform')\n\t\t\t\t\tappendTransform((code, filename) => {\n\t\t\t\t\t\tif (filename.endsWith(path.sep + 'index.js')) {\n\t\t\t\t\t\t\tconsole.log('js working');\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn code;\n\t\t\t\t\t});\n\t\t\t\t\tappendTransform((code, filename) => {\n\t\t\t\t\t\tif (filename.endsWith(path.sep + 'ts.ts')) {\n\t\t\t\t\t\t\tconsole.log('ts working');\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn code;\n\t\t\t\t\t}, '.ts');\n\t\t\t\t\t`,\n\t\t\t\t\t'node_modules/append-transform': ({ symlink }) => symlink(path.resolve('node_modules/append-transform'), 'junction'),\n\t\t\t\t});\n\n\t\t\t\tconst { stdout } = await execaNode('./index.js', {\n\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\tnodeOptions: [\n\t\t\t\t\t\t'--require',\n\t\t\t\t\t\t'./hook.js',\n\t\t\t\t\t\t'--require',\n\t\t\t\t\t\ttsxCjsPath,\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\texpect(stdout).toBe('js working\\nts working');\n\t\t\t});\n\n\t\t\tdescribe('register', ({ test }) => {\n\t\t\t\ttest('register / unregister', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'register.cjs': outdent`\n\t\t\t\t\t\tconst { register } = require(${JSON.stringify(tsxCjsApiPath)});\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\trequire('./file');\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tconsole.log('Fails as expected');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst unregister = register();\n\n\t\t\t\t\t\tconst loaded = require('./file');\n\t\t\t\t\t\tconsole.log(loaded.message);\n\n\t\t\t\t\t\t// Remove from cache\n\t\t\t\t\t\tconst loadedPath = require.resolve('./file');\n\t\t\t\t\t\tdelete require.cache[loadedPath];\n\n\t\t\t\t\t\tunregister();\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\trequire('./file');\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tconsole.log('Unregistered');\n\t\t\t\t\t\t}\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('register.cjs'), [], {\n\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t});\n\n\t\t\t\t\texpect(stdout).toBe('Fails as expected\\nfoo bar json file.ts\\nUnregistered');\n\t\t\t\t});\n\n\t\t\t\ttest('namespace', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'require.cjs': outdent`\n\t\t\t\t\t\tconst { expectErrors } = require('expect-errors');\n\t\t\t\t\t\tconst path = require('node:path');\n\t\t\t\t\t\tconst tsx = require(${JSON.stringify(tsxCjsApiPath)});\n\n\t\t\t\t\t\tconst api = tsx.register({ namespace: 'abcd' });\n\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t// Loading explicit/resolved file path should be ignored by loader (extensions)\n\t\t\t\t\t\t\t[() => require('./file.ts'), 'SyntaxError'],\n\n\t\t\t\t\t\t\t// resolver should preserve full file path when ignoring\n\t\t\t\t\t\t\t[() => require('./file.ts?asdf'), \"Cannot find module './file.ts?asdf'\"]\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconst { message, async } = api.require('./file', __filename);\n\t\t\t\t\t\tconsole.log(message);\n\t\t\t\t\t\tasync.then(m => console.log(m.default));\n\n\t\t\t\t\t\tapi.require('./tsx?query=1', __filename);\n\t\t\t\t\t\tapi.require('./jsx', __filename);\n\t\t\t\t\t\tapi.require('./dir?query=3', __filename);\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t...tsFiles,\n\n\t\t\t\t\t\t'tsx.tsx': 'console.log(\\'tsx\\');',\n\t\t\t\t\t\t'jsx.jsx': 'console.log(\\'jsx\\');',\n\t\t\t\t\t\t'dir/index.jsx': 'console.log(\\'dir\\');',\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('require.cjs'), [], {\n\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t});\n\n\t\t\t\t\texpect(stdout).toBe('foo bar json file.ts\\ntsx\\njsx\\ndir\\nasync');\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tdescribe('tsx.require()', ({ test }) => {\n\t\t\t\ttest('loads', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'require.cjs': outdent`\n\t\t\t\t\t\tconst path = require('node:path');\n\t\t\t\t\t\tconst tsx = require(${JSON.stringify(tsxCjsApiPath)});\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\trequire('./file');\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tconsole.log('Fails as expected');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst loaded = tsx.require('./file', __filename);\n\t\t\t\t\t\tconsole.log(loaded.message);\n\n\t\t\t\t\t\t// Can require core modules\n\t\t\t\t\t\ttsx.require('node:path', __filename);\n\t\t\t\t\t\ttsx.require('fs', __filename);\n\n\t\t\t\t\t\t// Remove from cache\n\t\t\t\t\t\tconst loadedPath = tsx.require.resolve('./file', __filename);\n\t\t\t\t\t\tconsole.log(loadedPath.split(path.sep).pop());\n\t\t\t\t\t\tdelete require.cache[loadedPath];\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\trequire('./file');\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tconsole.log('Unpolluted global require');\n\t\t\t\t\t\t}\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { stdout } = await execaNode('./require.cjs', [], {\n\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t});\n\n\t\t\t\t\texpect(stdout).toMatch(/Fails as expected\\nfoo bar json file.ts\\nfile.ts\\?namespace=\\d+\\nUnpolluted global require/);\n\t\t\t\t});\n\n\t\t\t\ttest('catchable', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'require.cjs': outdent`\n\t\t\t\t\t\tconst tsx = require(${JSON.stringify(tsxCjsApiPath)});\n\t\t\t\t\t\ttry { tsx.require('./syntax-error', __filename); } catch {}\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t'syntax-error.ts': 'if',\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { all } = await execaNode(fixture.getPath('require.cjs'), [], {\n\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\tall: true,\n\t\t\t\t\t});\n\t\t\t\t\texpect(all).toBe('');\n\t\t\t\t});\n\n\t\t\t\ttest('chainable', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'require.cjs': outdent`\n\t\t\t\t\t\tconst path = require('node:path');\n\t\t\t\t\t\tconst tsx = require(${JSON.stringify(tsxCjsApiPath)});\n\n\t\t\t\t\t\tconst unregister = tsx.register();\n\t\t\t\t\t\tconsole.log(require('./file').message);\n\t\t\t\t\t\tdelete require.cache[require.resolve('./file')];\n\n\t\t\t\t\t\tconst loaded = tsx.require('./file', __filename);\n\t\t\t\t\t\tconsole.log(loaded.message);\n\n\t\t\t\t\t\t// Remove from cache\n\t\t\t\t\t\tconst loadedPath = tsx.require.resolve('./file', __filename);\n\t\t\t\t\t\tdelete require.cache[loadedPath];\n\n\t\t\t\t\t\tconsole.log(require('./file').message);\n\t\t\t\t\t\tdelete require.cache[require.resolve('./file')];\n\n\t\t\t\t\t\tunregister();\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\trequire('./file');\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tconsole.log('Unregistered');\n\t\t\t\t\t\t}\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('require.cjs'), [], {\n\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t});\n\n\t\t\t\t\texpect(stdout).toBe('foo bar json file.ts\\nfoo bar json file.ts\\nfoo bar json file.ts\\nUnregistered');\n\t\t\t\t});\n\n\t\t\t\ttest('works with proxyquire (eslint tests)', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'index.js': outdent`\n\t\t\t\t\t\tconst proxyquire = require('proxyquire');\n\t\t\t\t\t\tconst tsx = require(${JSON.stringify(tsxCjsApiPath)});\n\n\t\t\t\t\t\ttsx.register();\n\n\t\t\t\t\t\tproxyquire('./test.js', {\n\t\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\t\tsep: 'hello world',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t\t`,\n\n\t\t\t\t\t\t'test.js': outdent`\n\t\t\t\t\t\tconst path = require('path');\n\t\t\t\t\t\tconsole.log(path.sep);\n\t\t\t\t\t\t`,\n\n\t\t\t\t\t\t'node_modules/proxyquire': ({ symlink }) => symlink(path.resolve('node_modules/proxyquire'), 'junction'),\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { stdout } = await execaNode('./index.js', {\n\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t});\n\n\t\t\t\t\texpect(stdout).toBe('hello world');\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\tdescribe('module', ({ describe, test }) => {\n\t\t\ttest('cli', async () => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t'index.ts': outdent`\n\t\t\t\t\timport { message } from \"./file\";\n\t\t\t\t\tconsole.log(message, new Error().stack);\n\t\t\t\t\t`,\n\t\t\t\t\t...tsFiles,\n\t\t\t\t});\n\n\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('index.ts'), {\n\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\tnodeOptions: [node.supports.moduleRegister ? '--import' : '--loader', tsxEsmPath],\n\t\t\t\t});\n\t\t\t\texpect(stdout).toContain('foo bar');\n\t\t\t\texpect(stdout).toContain('index.ts:2:22');\n\t\t\t});\n\n\t\t\ttest('cli - cjsInterop', async () => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'index.mts': 'import \"./file\"',\n\t\t\t\t\t...tsFiles,\n\t\t\t\t});\n\n\t\t\t\tconst { stderr } = await execaNode(fixture.getPath('index.mts'), {\n\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\tnodeOptions: [node.supports.moduleRegister ? '--import' : '--loader', tsxEsmPath],\n\t\t\t\t\treject: false,\n\t\t\t\t});\n\t\t\t\texpect(stderr).not.toContain('data:text/javascript');\n\t\t\t});\n\n\t\t\tif (node.supports.moduleRegister) {\n\t\t\t\ttest('module.register', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t'module-register.mjs': outdent`\n\t\t\t\t\t\timport { register } from 'node:module';\n\n\t\t\t\t\t\tawait import('./file.ts').catch((error) => {\n\t\t\t\t\t\t\tconsole.log('Fails as expected');\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tregister(${JSON.stringify(tsxEsmPath)}, {\n\t\t\t\t\t\t\tparentURL: import.meta.url,\n\t\t\t\t\t\t\tdata: true,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tconst { message } = await import('./file1.ts?nocache')\n\t\t\t\t\t\tconsole.log(message)\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('module-register.mjs'), [], {\n\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t});\n\n\t\t\t\t\texpect(stdout).toBe('Fails as expected\\nfoo bar json file1.ts?nocache');\n\t\t\t\t});\n\n\t\t\t\tdescribe('register / unregister', ({ test, describe }) => {\n\t\t\t\t\ttest('register / unregister', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait import('./file.ts?1');\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tconsole.log('Fails as expected 1');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tconst unregister = register();\n\n\t\t\t\t\t\t\t\tconst { message } = await import('./file1');\n\t\t\t\t\t\t\t\tconsole.log(message);\n\n\t\t\t\t\t\t\t\tawait unregister();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait import('./file1.ts?3');\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tconsole.log('Fails as expected 2');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tconst unregister = register();\n\n\t\t\t\t\t\t\t\tconst { message } = await import('./file1?4');\n\t\t\t\t\t\t\t\tconsole.log(message);\n\n\t\t\t\t\t\t\t\tawait unregister();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('register.mjs'), [], {\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t\treject: false,\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(stdout).toBe('Fails as expected 1\\nfoo bar json file1.ts\\nFails as expected 2\\nfoo bar json file1.ts?4');\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('onImport', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\n\t\t\t\t\t\t\tconst unregister = register({\n\t\t\t\t\t\t\t\tonImport(file) {\n\t\t\t\t\t\t\t\t\tconsole.log(file.split('/').pop());\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait import('./file');\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('register.mjs'), [], {\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(stdout).toMatch(/^lexer-[a-zA-Z0-9]+\\.mjs\\nfile\\.ts\\nfoo\\.ts\\njson\\.json\\npromises\\nbar\\.ts\\npkg\\.js\\nnode:process$/);\n\t\t\t\t\t}, {\n\t\t\t\t\t\tretry: 3,\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('namespace & onImport', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\t\timport { setTimeout } from 'node:timers/promises';\n\t\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\n\t\t\t\t\t\t\tconst api = register({\n\t\t\t\t\t\t\t\tnamespace: 'private',\n\t\t\t\t\t\t\t\tonImport(file) {\n\t\t\t\t\t\t\t\t\tconsole.log(file.split('/').pop());\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait api.import('./file', import.meta.url);\n\n\t\t\t\t\t\t\tawait setTimeout(100)\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('register.mjs'), [], {\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(stdout).toBe('file.ts\\nfoo.ts\\njson.json\\nbar.ts\\npkg.js');\n\t\t\t\t\t}, {\n\t\t\t\t\t\tretry: 3,\n\t\t\t\t\t});\n\n\t\t\t\t\tdescribe('tsconfig', ({ test }) => {\n\t\t\t\t\t\ttest('should ignore detected unresolvable tsconfig', async () => {\n\t\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t\t'tsconfig.json': createTsconfig({\n\t\t\t\t\t\t\t\t\textends: 'doesnt-exist',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\t\t\t\t\t\t\t\tregister();\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait execaNode('register.mjs', [], {\n\t\t\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\ttest('disable lookup', async () => {\n\t\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t\t'tsconfig.json': createTsconfig({\n\t\t\t\t\t\t\t\t\textends: 'doesnt-exist',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\t\t\t\t\t\t\t\tregister({\n\t\t\t\t\t\t\t\t\ttsconfig: false,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait execaNode('register.mjs', [], {\n\t\t\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\ttest('custom path', async () => {\n\t\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t\t'tsconfig.json': createTsconfig({\n\t\t\t\t\t\t\t\t\textends: 'doesnt-exist',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t'tsconfig-custom.json': createTsconfig({\n\t\t\t\t\t\t\t\t\tcompilerOptions: {\n\t\t\t\t\t\t\t\t\t\tjsxFactory: 'Array',\n\t\t\t\t\t\t\t\t\t\tjsxFragmentFactory: 'null',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\t\t\t\t\t\t\t\tregister({\n\t\t\t\t\t\t\t\t\ttsconfig: './tsconfig-custom.json',\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tawait import('./tsx.tsx');\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t\t'tsx.tsx': outdent`\n\t\t\t\t\t\t\t\tconsole.log(<>hi</>);\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst { stdout } = await execaNode('register.mjs', [], {\n\t\t\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\texpect(stdout).toBe('[ null, null, \\'hi\\' ]');\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\ttest('custom path - invalid', async () => {\n\t\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\t\t\t\t\t\t\t\tregister({\n\t\t\t\t\t\t\t\t\ttsconfig: './doesnt-exist',\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tawait import('./tsx.tsx');\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t\t'tsx.tsx': outdent`\n\t\t\t\t\t\t\t\tconsole.log(<>hi</>);\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst { exitCode, stderr } = await execaNode('register.mjs', [], {\n\t\t\t\t\t\t\t\treject: false,\n\t\t\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\texpect(exitCode).toBe(1);\n\t\t\t\t\t\t\texpect(stderr).toMatch('Cannot resolve tsconfig at path');\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\ttest('fallsback to env var', async () => {\n\t\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t\t'tsconfig.json': createTsconfig({\n\t\t\t\t\t\t\t\t\textends: 'doesnt-exist',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t'tsconfig-custom.json': createTsconfig({\n\t\t\t\t\t\t\t\t\tcompilerOptions: {\n\t\t\t\t\t\t\t\t\t\tjsxFactory: 'Array',\n\t\t\t\t\t\t\t\t\t\tjsxFragmentFactory: 'null',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\t\t\t\t\t\t\t\tregister();\n\t\t\t\t\t\t\t\tawait import('./tsx.tsx');\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t\t'tsx.tsx': outdent`\n\t\t\t\t\t\t\t\tconsole.log(<>hi</>);\n\t\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst { stdout } = await execaNode('register.mjs', [], {\n\t\t\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t\t\tenv: {\n\t\t\t\t\t\t\t\t\tTSX_TSCONFIG_PATH: 'tsconfig-custom.json',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\texpect(stdout).toBe('[ null, null, \\'hi\\' ]');\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tdescribe('tsImport()', ({ test }) => {\n\t\t\t\t\ttest('module', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t'import.mjs': outdent`\n\t\t\t\t\t\t\timport { tsImport } from ${JSON.stringify(tsxEsmApiPath)};\n\n\t\t\t\t\t\t\tawait import('./file.ts').catch((error) => {\n\t\t\t\t\t\t\t\tconsole.log('Fails as expected 1');\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst { message } = await tsImport('./file.ts', import.meta.url);\n\t\t\t\t\t\t\tconsole.log(message);\n\n\t\t\t\t\t\t\t// Loads cts vis CJS namespace even if there are no exports\n\t\t\t\t\t\t\tawait tsImport('./cjs/exports-no.cts', import.meta.url).catch((error) => console.log(error.constructor.name))\n\n\t\t\t\t\t\t\tconst cts = await tsImport('./cjs/exports-yes.cts', import.meta.url).then(({ cjsReexport, esmSyntax }) => \\`\\${cjsReexport} \\${esmSyntax}\\`, err => err.constructor.name);\n\t\t\t\t\t\t\tconsole.log(cts);\n\n\t\t\t\t\t\t\tconst cjs = await tsImport('./cjs/reexport.cjs?query', import.meta.url).then(({ cjsReexport, esmSyntax }) => \\`\\${cjsReexport} \\${esmSyntax}\\`, err => err.constructor.name);\n\t\t\t\t\t\t\tconsole.log(cjs);\n\n\t\t\t\t\t\t\tawait tsImport('@a/b.cjs', import.meta.url);\n\n\t\t\t\t\t\t\tconst { message: message2 } = await tsImport('./file.ts?with-query', import.meta.url);\n\t\t\t\t\t\t\tconsole.log(message2);\n\n\t\t\t\t\t\t\t// Global not polluted\n\t\t\t\t\t\t\tawait import('./file.ts?nocache').catch((error) => {\n\t\t\t\t\t\t\t\tconsole.log('Fails as expected 2');\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst { stdout } = await execaNode('./import.mjs', [], {\n\t\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\texpect(stdout).toMatch(new RegExp([\n\t\t\t\t\t\t\t'Fails as expected 1',\n\t\t\t\t\t\t\tString.raw`foo bar json file\\.ts\\?tsx-namespace=\\d+`,\n\t\t\t\t\t\t\t'cts loaded',\n\t\t\t\t\t\t\t'cjsReexport esm syntax',\n\t\t\t\t\t\t\t'cjsReexport esm syntax',\n\t\t\t\t\t\t\tString.raw`foo bar json file\\.ts\\?with-query&tsx-namespace=\\d+`,\n\t\t\t\t\t\t\t'Fails as expected 2',\n\t\t\t\t\t\t].join(String.raw`\\n`)));\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('commonjs', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t'import.cjs': outdent`\n\t\t\t\t\t\t\tconst { tsImport } = require(${JSON.stringify(tsxEsmApiCjsPath)});\n\n\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\tawait import('./file.ts').catch((error) => {\n\t\t\t\t\t\t\t\t\tconsole.log('Fails as expected 1');\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tconst { message } = await tsImport('./file.ts', __filename);\n\t\t\t\t\t\t\t\tconsole.log(message);\n\n\t\t\t\t\t\t\t\tconst { message: message2 } = await tsImport('./file.ts?with-query', __filename);\n\t\t\t\t\t\t\t\tconsole.log(message2);\n\n\t\t\t\t\t\t\t\tconst cts = await tsImport('./cjs/exports-yes.cts?query', __filename).then(({ cjsReexport, esmSyntax }) => \\`\\${cjsReexport} \\${esmSyntax}\\`, err => err.constructor.name);\n\t\t\t\t\t\t\t\tconsole.log(cts);\n\n\t\t\t\t\t\t\t\tconst cjs = await tsImport('./cjs/reexport.cjs?query', __filename).then(({ cjsReexport, esmSyntax }) => \\`\\${cjsReexport} \\${esmSyntax}\\`, err => err.constructor.name);\n\t\t\t\t\t\t\t\tconsole.log(cjs);\n\n\t\t\t\t\t\t\t\tawait tsImport('@a/b.cjs', __filename);\n\n\t\t\t\t\t\t\t\t// Global not polluted\n\t\t\t\t\t\t\t\tawait import('./file.ts?nocache').catch((error) => {\n\t\t\t\t\t\t\t\t\tconsole.log('Fails as expected 2');\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t})();\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('import.cjs'), [], {\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\texpect(stdout).toMatch(new RegExp([\n\t\t\t\t\t\t\t'Fails as expected 1',\n\t\t\t\t\t\t\tString.raw`foo bar json file\\.ts\\?tsx-namespace=\\d+`,\n\t\t\t\t\t\t\tString.raw`foo bar json file\\.ts\\?with-query&tsx-namespace=\\d+`,\n\t\t\t\t\t\t\t'cjsReexport esm syntax',\n\t\t\t\t\t\t\t'cjsReexport esm syntax',\n\t\t\t\t\t\t\t'Fails as expected 2',\n\t\t\t\t\t\t].join(String.raw`\\n`)));\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('mts from commonjs', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'import.cjs': outdent`\n\t\t\t\t\t\t\tconst { tsImport } = require(${JSON.stringify(tsxEsmApiCjsPath)});\n\n\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\tconst { message } = await tsImport('./file.mts', __filename);\n\t\t\t\t\t\t\t\tconsole.log(message);\n\t\t\t\t\t\t\t})();\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t'file.mts': 'export const message = \"foo bar\"',\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('import.cjs'), [], {\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(stdout).toBe('foo bar');\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('namespace allows async nested calls without cross contamination', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t'import.mjs': outdent`\n\t\t\t\t\t\t\timport { tsImport } from ${JSON.stringify(tsxEsmApiPath)};\n\t\t\t\t\t\t\ttsImport('./file.ts', import.meta.url);\n\t\t\t\t\t\t\timport('./file.ts').catch(() => console.log('Fails as expected'))\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t'file.ts': 'import(\\'./foo.ts\\')',\n\t\t\t\t\t\t\t'foo.ts': `\n\t\t\t\t\t\t\tenum Test {\n\t\t\t\t\t\t\t\tFoo = 'foo',\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconsole.log(Test.Foo);\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst { stdout, stderr } = await execaNode(fixture.getPath('import.mjs'), [], {\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t\treject: false,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\texpect(stdout).toBe('Fails as expected\\nfoo');\n\t\t\t\t\t\texpect(stderr).toBe('');\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('onImport & doesnt cache files', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t'import.mjs': outdent`\n\t\t\t\t\t\t\timport { setTimeout } from 'node:timers/promises';\n\t\t\t\t\t\t\timport { tsImport } from ${JSON.stringify(tsxEsmApiPath)};\n\t\t\t\t\t\t\tconst dependenciesA = [];\n\t\t\t\t\t\t\tawait tsImport('./file.ts', {\n\t\t\t\t\t\t\t\tparentURL: import.meta.url,\n\t\t\t\t\t\t\t\tonImport(file) {\n\t\t\t\t\t\t\t\t\tdependenciesA.push(file);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst dependenciesB = [];\n\t\t\t\t\t\t\tawait tsImport('./file.ts', {\n\t\t\t\t\t\t\t\tparentURL: import.meta.url,\n\t\t\t\t\t\t\t\tonImport(file) {\n\t\t\t\t\t\t\t\t\tdependenciesB.push(file);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// wait for async import() to finish\n\t\t\t\t\t\t\tawait setTimeout(100)\n\n\t\t\t\t\t\t\tif (JSON.stringify(dependenciesA) !== JSON.stringify(dependenciesB)) {\n\t\t\t\t\t\t\t\tconsole.log({\n\t\t\t\t\t\t\t\t\tdependenciesA,\n\t\t\t\t\t\t\t\t\tdependenciesB,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tprocess.exitCode = 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t'file.ts': 'import \"./foo.ts\"; import(\\'./bar.ts\\')',\n\t\t\t\t\t\t\t'foo.ts': 'console.log(\\'foo\\' as string)',\n\t\t\t\t\t\t\t'bar.ts': 'import(\\'./foo.ts\\')',\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst { stdout } = await execaNode(fixture.getPath('import.mjs'), [], {\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(stdout).toBe('foo\\nfoo');\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('tsconfig disable', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t\t'tsconfig.json': createTsconfig({ extends: 'doesnt-exist' }),\n\t\t\t\t\t\t\t'import.mjs': outdent`\n\t\t\t\t\t\t\timport { tsImport } from ${JSON.stringify(tsxEsmApiPath)};\n\n\t\t\t\t\t\t\tawait tsImport('./file.ts', {\n\t\t\t\t\t\t\t\tparentURL: import.meta.url,\n\t\t\t\t\t\t\t\ttsconfig: false,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait execaNode('import.mjs', [], {\n\t\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\ttest('no module.register error', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t'register.mjs': outdent`\n\t\t\t\t\t\timport { register } from ${JSON.stringify(tsxEsmApiPath)};\n\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst unregister = register();\n\n\t\t\t\t\t\t\tconst { message } = await import('./file?2');\n\t\t\t\t\t\t\tconsole.log(message);\n\n\t\t\t\t\t\t\tawait unregister();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t...tsFiles,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { stderr } = await execaNode(fixture.getPath('register.mjs'), [], {\n\t\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\t\treject: false,\n\t\t\t\t\t});\n\t\t\t\t\texpect(stderr).toMatch(`This version of Node.js (v${node.version}) does not support module.register(). Please upgrade to Node v18.19 or v20.6 and above.`);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "tests/specs/cli.ts",
    "content": "import { setTimeout } from 'node:timers/promises';\nimport { testSuite, expect } from 'manten';\nimport { createFixture } from 'fs-fixture';\nimport packageJson from '../../package.json';\nimport { ptyShell, isWindows } from '../utils/pty-shell/index.js';\nimport { expectMatchInOrder } from '../utils/expect-match-in-order.js';\nimport { tsxPath, type NodeApis } from '../utils/tsx.js';\nimport { isProcessAlive } from '../utils/is-process-alive.js';\n\nexport default testSuite(({ describe }, node: NodeApis) => {\n\tconst { tsx } = node;\n\n\tdescribe('CLI', ({ describe, test }) => {\n\t\tdescribe('argv', async ({ describe, onFinish }) => {\n\t\t\tconst fixture = await createFixture({\n\t\t\t\t// Unnecessary TS to test syntax\n\t\t\t\t'log-argv.ts': 'console.log(JSON.stringify(process.argv) as string)',\n\t\t\t});\n\t\t\tonFinish(async () => await fixture.rm());\n\n\t\t\tdescribe('version', ({ test }) => {\n\t\t\t\ttest('shows version', async () => {\n\t\t\t\t\tconst tsxProcess = await tsx(['--version']);\n\n\t\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t\t\texpect(tsxProcess.stdout).toBe(`tsx v${packageJson.version}\\nnode v${node.version}`);\n\t\t\t\t\texpect(tsxProcess.stderr).toBe('');\n\t\t\t\t});\n\n\t\t\t\ttest('doesn\\'t show version with file', async () => {\n\t\t\t\t\tconst tsxProcess = await tsx([\n\t\t\t\t\t\tfixture.getPath('log-argv.ts'),\n\t\t\t\t\t\t'--version',\n\t\t\t\t\t]);\n\n\t\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t\t\texpect(tsxProcess.stdout).toMatch('\"--version\"');\n\t\t\t\t\texpect(tsxProcess.stdout).not.toMatch(packageJson.version);\n\t\t\t\t\texpect(tsxProcess.stderr).toBe('');\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tdescribe('help', ({ test }) => {\n\t\t\t\ttest('shows help', async () => {\n\t\t\t\t\tconst tsxProcess = await tsx(['--help']);\n\n\t\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t\t\texpect(tsxProcess.stdout).toMatch('Node.js runtime enhanced with esbuild for loading TypeScript & ESM');\n\t\t\t\t\texpect(tsxProcess.stdout).toMatch('Usage: node [options] [ script.js ] [arguments]');\n\t\t\t\t\texpect(tsxProcess.stderr).toBe('');\n\t\t\t\t});\n\n\t\t\t\ttest('doesn\\'t show help with file', async () => {\n\t\t\t\t\tconst tsxProcess = await tsx([\n\t\t\t\t\t\tfixture.getPath('log-argv.ts'),\n\t\t\t\t\t\t'--help',\n\t\t\t\t\t]);\n\n\t\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t\t\texpect(tsxProcess.stdout).toMatch('\"--help\"');\n\t\t\t\t\texpect(tsxProcess.stdout).not.toMatch('tsx');\n\t\t\t\t\texpect(tsxProcess.stderr).toBe('');\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\tdescribe('eval & print', ({ test }) => {\n\t\t\ttest('TypeScript', async () => {\n\t\t\t\tconst tsxProcess = await tsx([\n\t\t\t\t\t'--eval',\n\t\t\t\t\t'console.log(require(\"fs\") && module as string)',\n\t\t\t\t]);\n\n\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t\texpect(tsxProcess.stdout).toMatch(\"id: '[eval]'\");\n\t\t\t\texpect(tsxProcess.stderr).toBe('');\n\t\t\t});\n\n\t\t\ttest('--input-type=module is respected', async () => {\n\t\t\t\tconst tsxProcess = await tsx([\n\t\t\t\t\t'--input-type=module',\n\t\t\t\t\t'--eval',\n\t\t\t\t\t'console.log(typeof require)',\n\t\t\t\t]);\n\n\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t\texpect(tsxProcess.stdout).toBe('undefined');\n\t\t\t\texpect(tsxProcess.stderr).toBe('');\n\t\t\t});\n\n\t\t\ttest('--print', async () => {\n\t\t\t\tconst tsxProcess = await tsx([\n\t\t\t\t\t'--print',\n\t\t\t\t\t'require(\"fs\") && module as string',\n\t\t\t\t]);\n\n\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t\texpect(tsxProcess.stdout).toMatch(\"id: '[eval]'\");\n\t\t\t\texpect(tsxProcess.stderr).toBe('');\n\t\t\t});\n\t\t});\n\n\t\tif (\n\t\t\tnode.supports.cliTestFlag\n\n\t\t\t// node --test is broken in v20.0.0\n\t\t\t// https://github.com/nodejs/node/issues/48467\n\t\t\t&& node.version !== '20.0.0'\n\t\t) {\n\t\t\ttest('Node.js test runner', async () => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'test.ts': `\n\t\t\t\t\timport { test } from 'node:test';\n\t\t\t\t\timport assert from 'assert';\n\n\t\t\t\t\ttest('some passing test', () => {\n\t\t\t\t\t\tassert.strictEqual(1, 1 as number);\n\t\t\t\t\t});\n\t\t\t\t\t`,\n\t\t\t\t});\n\n\t\t\t\tconst tsxProcess = await tsx(\n\t\t\t\t\t[\n\t\t\t\t\t\t'--test',\n\t\t\t\t\t\t...(\n\t\t\t\t\t\t\tnode.supports.testRunnerGlob\n\t\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t\t: ['test.ts']\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t\tfixture.path,\n\t\t\t\t);\n\n\t\t\t\tif (node.supports.testRunnerGlob) {\n\t\t\t\t\texpect(tsxProcess.stdout).toMatch(/some passing test( \\(.+ms\\))?\\n/);\n\t\t\t\t} else {\n\t\t\t\t\texpect(tsxProcess.stdout).toMatch('# pass 1\\n');\n\t\t\t\t}\n\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t}, 10_000);\n\t\t}\n\n\t\tdescribe('Signals', async ({ describe, test, onFinish }) => {\n\t\t\tconst signals = ['SIGINT', 'SIGTERM'];\n\t\t\tconst fixture = await createFixture({\n\t\t\t\t'propagates-signal.js': 'process.exit(process.argv[2])',\n\n\t\t\t\t'catch-signals.js': `\n\t\t\t\tconst signals = ${JSON.stringify(signals)};\n\t\t\t\t\n\t\t\t\tfor (const name of signals) {\n\t\t\t\t\tprocess.once(name, () => {\n\t\t\t\t\t\tconsole.log(name, 'PRESS AGAIN');\n\t\t\t\t\t\tprocess.once(name, () => {\n\t\t\t\t\t\t\tprocess.exit(200);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tsetTimeout(() => {}, 1e5);\n\t\t\t\tconsole.log('READY');\t\t\t\t\n\t\t\t\t`,\n\t\t\t\t'keep-alive.js': `\n\t\t\t\tsetTimeout(() => {}, 1e5);\n\t\t\t\tconsole.log('READY');\n\t\t\t\t`,\n\t\t\t\t'infinite-loop.js': `\n\t\t\t\tconsole.log(process.pid);\n\t\t\t\twhile (true) {}\n\t\t\t\t`,\n\t\t\t\t'ignores-signals.js': `\n\t\t\t\tconsole.log(process.pid);\n\t\t\t\tprocess.on('SIGINT', () => {\n\t\t\t\t\tconsole.log('Refusing SIGINT');\n\t\t\t\t});\n\t\t\t\tprocess.on('SIGTERM', () => {\n\t\t\t\t\tconsole.log('Refusing SIGTERM');\n\t\t\t\t});\n\t\t\t\tsetTimeout(() => {}, 1e5);\n\t\t\t\t`,\n\t\t\t\t'hidden-signals-handler.js': `\n\t\t\t\tconsole.log('process.listeners().length = ' + process.listeners('SIGINT').length);\n\t\t\t\tconsole.log('process.listenerCount() = ' + process.listenerCount('SIGINT'));\n\t\t\t\t`,\n\t\t\t});\n\t\t\tonFinish(async () => await fixture.rm());\n\n\t\t\ttest('Propagates signal', async () => {\n\t\t\t\tconst exitCode = Math.floor(Math.random() * 100);\n\t\t\t\tconst tsxProcess = await tsx([\n\t\t\t\t\tfixture.getPath('propagates-signal.js'),\n\t\t\t\t\texitCode.toString(),\n\t\t\t\t]);\n\t\t\t\texpect(tsxProcess.exitCode).toBe(exitCode);\n\t\t\t}, 10_000);\n\n\t\t\tdescribe('Relays kill signal', ({ test }) => {\n\t\t\t\tfor (const signal of signals) {\n\t\t\t\t\ttest(signal, async ({ onTestFail }) => {\n\t\t\t\t\t\tconst tsxProcess = tsx([\n\t\t\t\t\t\t\tfixture.getPath('catch-signals.js'),\n\t\t\t\t\t\t]);\n\n\t\t\t\t\t\ttsxProcess.stdout!.once('data', () => {\n\t\t\t\t\t\t\ttsxProcess.kill(signal, {\n\t\t\t\t\t\t\t\tforceKillAfterTimeout: false,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\ttsxProcess.stdout!.once('data', () => {\n\t\t\t\t\t\t\t\ttsxProcess.kill(signal, {\n\t\t\t\t\t\t\t\t\tforceKillAfterTimeout: false,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst tsxProcessResolved = await tsxProcess;\n\n\t\t\t\t\t\tonTestFail(() => {\n\t\t\t\t\t\t\tconsole.log(tsxProcessResolved);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (process.platform === 'win32') {\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Windows doesn't support sending signals to processes.\n\t\t\t\t\t\t\t * https://nodejs.org/api/process.html#signal-events\n\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t * Sending SIGINT, SIGTERM, and SIGKILL will cause the unconditional termination\n\t\t\t\t\t\t\t * of the target process, and afterwards, subprocess will report that the process\n\t\t\t\t\t\t\t * was terminated by signal.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\texpect(tsxProcessResolved.stdout).toBe('READY');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\texpect(tsxProcessResolved.exitCode).toBe(200);\n\t\t\t\t\t\t\texpectMatchInOrder(tsxProcessResolved.stdout, [\n\t\t\t\t\t\t\t\t'READY\\n',\n\t\t\t\t\t\t\t\t`${signal} PRESS AGAIN`,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, {\n\t\t\t\t\t\ttimeout: 10_000,\n\t\t\t\t\t\tretry: 3,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttest('Kills child when unresponsive (infinite loop)', async () => {\n\t\t\t\tconst tsxProcess = tsx([\n\t\t\t\t\tfixture.getPath('infinite-loop.js'),\n\t\t\t\t]);\n\n\t\t\t\tconst childPid = await new Promise<number>((resolve) => {\n\t\t\t\t\ttsxProcess.stdout!.once('data', (data) => {\n\t\t\t\t\t\tresolve(Number(data.toString()));\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\ttsxProcess.kill('SIGINT', {\n\t\t\t\t\tforceKillAfterTimeout: false,\n\t\t\t\t});\n\n\t\t\t\tconst result = await tsxProcess;\n\n\t\t\t\t/**\n\t\t\t\t * https://nodejs.org/api/process.html#signal-events\n\t\t\t\t * Sending SIGINT, SIGTERM, and SIGKILL will cause the unconditional termination of\n\t\t\t\t * the target process, and afterwards, subprocess will report that the process was\n\t\t\t\t * terminated by signal.\n\t\t\t\t */\n\t\t\t\tif (process.platform !== 'win32') {\n\t\t\t\t\t// This is the exit code I get from testing manually with Node\n\t\t\t\t\texpect(result.exitCode).toBe(130);\n\t\t\t\t}\n\n\t\t\t\t// Enforce that child process is killed\n\t\t\t\texpect(isProcessAlive(childPid!)).toBe(false);\n\t\t\t}, 10_000);\n\n\t\t\ttest('Doesn\\'t kill child when responsive (ignores signal)', async () => {\n\t\t\t\tconst tsxProcess = tsx([\n\t\t\t\t\tfixture.getPath('ignores-signals.js'),\n\t\t\t\t]);\n\n\t\t\t\tconst childPid = await new Promise<number>((resolve) => {\n\t\t\t\t\ttsxProcess.stdout!.once('data', (data) => {\n\t\t\t\t\t\tresolve(Number(data.toString()));\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// Send SIGINT to child\n\t\t\t\ttsxProcess.kill('SIGINT', {\n\t\t\t\t\tforceKillAfterTimeout: false,\n\t\t\t\t});\n\n\t\t\t\tawait setTimeout(500);\n\n\t\t\t\tif (process.platform === 'win32') {\n\t\t\t\t\texpect(isProcessAlive(childPid!)).toBe(false);\n\t\t\t\t} else {\n\t\t\t\t\texpect(isProcessAlive(childPid!)).toBe(true);\n\t\t\t\t\tprocess.kill(childPid!, 'SIGKILL');\n\t\t\t\t\t// Note: SIGKILLing tsx process will leave the child hanging\n\n\t\t\t\t\tconst result = await tsxProcess;\n\n\t\t\t\t\t// This is the exit code I get from testing manually with Node\n\t\t\t\t\texpect(result.exitCode).toBe(137);\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\ttimeout: 10_000,\n\t\t\t\tretry: 3,\n\t\t\t});\n\n\t\t\ttest('Relay signal handlers are properly hidden', async () => {\n\t\t\t\tconst tsxProcess = tsx([\n\t\t\t\t\tfixture.getPath('hidden-signals-handler.js'),\n\t\t\t\t]);\n\n\t\t\t\tconst result = await tsxProcess;\n\n\t\t\t\texpect(result.stdout).toBe('process.listeners().length = 0\\nprocess.listenerCount() = 0');\n\t\t\t\texpect(result.exitCode).toBe(0);\n\t\t\t});\n\n\t\t\tdescribe('Ctrl + C', ({ test }) => {\n\t\t\t\tconst CtrlC = '\\u0003';\n\n\t\t\t\ttest('Exit code', async ({ onTestFail }) => {\n\t\t\t\t\tconst shell = ptyShell();\n\n\t\t\t\t\tonTestFail(() => {\n\t\t\t\t\t\tconsole.log({ stdout: shell.getOutput() });\n\t\t\t\t\t});\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\t\t\t\t\t// Windows doesn't support shebangs\n\t\t\t\t\tshell.type(`${node.path} ${tsxPath} ${fixture.getPath('keep-alive.js')}`);\n\n\t\t\t\t\tawait shell.waitForLine(/READY/);\n\t\t\t\t\tshell.press(CtrlC);\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\t\t\t\t\tshell.type(`echo EXIT_CODE: ${isWindows ? '$LastExitCode' : '$?'}`);\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\n\t\t\t\t\texpect(await shell.close()).toMatch(/EXIT_CODE:\\s+130/);\n\t\t\t\t}, 10_000);\n\n\t\t\t\ttest('Catchable', async ({ onTestFail }) => {\n\t\t\t\t\tconst shell = ptyShell();\n\n\t\t\t\t\tonTestFail(() => {\n\t\t\t\t\t\tconsole.log({ stdout: shell.getOutput() });\n\t\t\t\t\t});\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\t\t\t\t\tshell.type(`${node.path} ${tsxPath} ${fixture.getPath('catch-signals.js')}`);\n\n\t\t\t\t\tawait shell.waitForLine(/READY/);\n\t\t\t\t\tshell.press(CtrlC);\n\n\t\t\t\t\tawait shell.waitForLine(/PRESS AGAIN/);\n\t\t\t\t\tshell.press(CtrlC);\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\t\t\t\t\tshell.type(`echo EXIT_CODE: ${isWindows ? '$LastExitCode' : '$?'}`);\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\n\t\t\t\t\texpectMatchInOrder(await shell.close(), [\n\t\t\t\t\t\t'READY\\r\\n',\n\t\t\t\t\t\tprocess.platform === 'win32' ? '' : '^C',\n\t\t\t\t\t\t'SIGINT PRESS AGAIN\\r\\n',\n\t\t\t\t\t\t/EXIT_CODE:\\s+200/,\n\t\t\t\t\t]);\n\t\t\t\t}, {\n\t\t\t\t\ttimeout: 10_000,\n\t\t\t\t\tretry: 3,\n\t\t\t\t});\n\n\t\t\t\ttest('Infinite loop', async ({ onTestFail }) => {\n\t\t\t\t\tconst shell = ptyShell();\n\n\t\t\t\t\tonTestFail(() => {\n\t\t\t\t\t\tconsole.log({ stdout: shell.getOutput() });\n\t\t\t\t\t});\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\t\t\t\t\t// Windows doesn't support shebangs\n\t\t\t\t\tshell.type(`${node.path} ${tsxPath} ${fixture.getPath('infinite-loop.js')}`);\n\n\t\t\t\t\tawait shell.waitForLine(/^\\r?\\d+$/);\n\t\t\t\t\tshell.press(CtrlC);\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\t\t\t\t\tshell.type(`echo EXIT_CODE: ${isWindows ? '$LastExitCode' : '$?'}`);\n\n\t\t\t\t\tawait shell.waitForPrompt();\n\n\t\t\t\t\texpect(await shell.close()).toMatch(/EXIT_CODE:\\s+130/);\n\t\t\t\t}, 10_000);\n\t\t\t});\n\t\t});\n\n\t\ttest('relays ipc message to child and back', async () => {\n\t\t\tawait using fixture = await createFixture({\n\t\t\t\t'file.js': `\n\t\t\t\tprocess.on('message', (received) => {\n\t\t\t\t\tprocess.send('goodbye');\n\t\t\t\t\tprocess.exit();\n\t\t\t\t});\n\t\t\t\t`,\n\t\t\t});\n\n\t\t\tconst tsxProcess = tsx(['file.js'], {\n\t\t\t\tcwd: fixture.path,\n\t\t\t\tstdio: ['ipc'],\n\t\t\t\treject: false,\n\t\t\t});\n\n\t\t\ttsxProcess.send('hello');\n\t\t\tconst received = await new Promise((resolve) => {\n\t\t\t\ttsxProcess.once('message', resolve);\n\t\t\t});\n\t\t\texpect(received).toBe('goodbye');\n\n\t\t\tawait tsxProcess;\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "tests/specs/loaders.ts",
    "content": "import { testSuite, expect } from 'manten';\nimport { createFixture } from 'fs-fixture';\nimport type { NodeApis } from '../utils/tsx.js';\nimport { createPackageJson } from '../fixtures.js';\n\nexport default testSuite(({ describe }, node: NodeApis) => {\n\tdescribe('Loaders', ({ describe }) => {\n\t\tdescribe('Hooks', async ({ test, onFinish }) => {\n\t\t\tconst fixture = await createFixture({\n\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\n\t\t\t\t'ts.ts': `\n\t\t\t\timport fs from 'node:fs';\n\n\t\t\t\tconsole.log(Boolean(fs) as unknown as string);\n\t\t\t\t`,\n\t\t\t\t'mts.mts': `\n\t\t\t\timport fs from 'node:fs';\n\n\t\t\t\tconsole.log(JSON.stringify([Boolean(fs) as unknown as string, import.meta.url]));\n\t\t\t\t`,\n\t\t\t});\n\t\t\tonFinish(async () => await fixture.rm());\n\n\t\t\ttest('.ts', async () => {\n\t\t\t\tconst tsxResult = await node.hook(['./ts.ts'], fixture.path);\n\n\t\t\t\texpect(tsxResult.stdout).toBe('true');\n\t\t\t\tif (node.supports.moduleRegister) {\n\t\t\t\t\texpect(tsxResult.stderr).toBe('');\n\t\t\t\t} else {\n\t\t\t\t\texpect(tsxResult.stderr).toMatch('ExperimentalWarning: Custom ESM Loaders is an experimental feature');\n\t\t\t\t}\n\t\t\t\texpect(tsxResult.exitCode).toBe(0);\n\t\t\t});\n\n\t\t\ttest('.mts', async () => {\n\t\t\t\tconst tsxResult = await node.hook(['./mts.mts'], fixture.path);\n\n\t\t\t\tconst [imported, importMetaUrl] = JSON.parse(tsxResult.stdout);\n\t\t\t\texpect(imported).toBe(true);\n\t\t\t\texpect(importMetaUrl.endsWith('/mts.mts')).toBeTruthy();\n\n\t\t\t\tif (node.supports.moduleRegister) {\n\t\t\t\t\texpect(tsxResult.stderr).toBe('');\n\t\t\t\t} else {\n\t\t\t\t\texpect(tsxResult.stderr).toMatch('ExperimentalWarning: Custom ESM Loaders is an experimental feature');\n\t\t\t\t}\n\t\t\t\texpect(tsxResult.exitCode).toBe(0);\n\t\t\t});\n\t\t});\n\n\t\tdescribe('CJS patching', async ({ test }) => {\n\t\t\tconst fixture = await createFixture({\n\t\t\t\t'package.json': createPackageJson({ type: 'commonjs' }),\n\n\t\t\t\t'ts.ts': `\n\t\t\t\timport fs from 'node:fs';\n\n\t\t\t\tconsole.log(Boolean(fs) as unknown as string);\n\t\t\t\t`,\n\t\t\t\t'cts.cts': `\n\t\t\t\timport fs from 'node:fs';\n\n\t\t\t\tconsole.log(Boolean(fs) as unknown as string);\n\t\t\t\t`,\n\t\t\t\t'mts.mts': `\n\t\t\t\timport fs from 'node:fs';\n\n\t\t\t\tconsole.log(Boolean(fs) as unknown as string, import.meta.url);\n\t\t\t\t`,\n\t\t\t});\n\n\t\t\ttest('.ts', async () => {\n\t\t\t\tconst tsxResult = await node.cjsPatched(['./ts.ts'], fixture.path);\n\n\t\t\t\texpect(tsxResult.stdout).toBe('true');\n\t\t\t\texpect(tsxResult.stderr).toBe('');\n\t\t\t\texpect(tsxResult.exitCode).toBe(0);\n\t\t\t});\n\n\t\t\t// TODO: Investigate why this works -- it shouldnt\n\t\t\t// test('should not be able to load .mjs', async () => {\n\t\t\t// \tconst tsxResult = await node.cjsPatched(['./mts.mts'], fixture.path);\n\n\t\t\t// \texpect(tsxResult.stdout).toBe('true');\n\t\t\t// \texpect(tsxResult.stderr).toBe('');\n\t\t\t// \texpect(tsxResult.exitCode).toBe(0);\n\t\t\t// });\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "tests/specs/repl.ts",
    "content": "import { testSuite } from 'manten';\nimport { tsx } from '../utils/tsx';\nimport { processInteract } from '../utils/process-interact.js';\n\nexport default testSuite(async ({ describe }) => {\n\tdescribe('REPL', ({ test }) => {\n\t\ttest('handles ts', async () => {\n\t\t\tconst tsxProcess = tsx({\n\t\t\t\targs: ['--interactive'],\n\t\t\t});\n\n\t\t\tawait processInteract(\n\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t[\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('> ')) {\n\t\t\t\t\t\t\ttsxProcess.stdin!.write('const message: string = \"SUCCESS\"\\r');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('> ')) {\n\t\t\t\t\t\t\ttsxProcess.stdin!.write('message\\r');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdata => data.includes('SUCCESS'),\n\t\t\t\t],\n\t\t\t\t5000,\n\t\t\t);\n\n\t\t\ttsxProcess.kill();\n\t\t}, 40_000);\n\n\t\ttest('doesn\\'t error on require', async () => {\n\t\t\tconst tsxProcess = tsx({\n\t\t\t\targs: ['--interactive'],\n\t\t\t});\n\n\t\t\tawait processInteract(\n\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t[\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('> ')) {\n\t\t\t\t\t\t\ttsxProcess.stdin!.write('require(\"path\")\\r');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdata => data.includes('[Function: resolve]'),\n\t\t\t\t],\n\t\t\t\t5000,\n\t\t\t);\n\n\t\t\ttsxProcess.kill();\n\t\t}, 40_000);\n\n\t\ttest('supports incomplete expression in segments', async () => {\n\t\t\tconst tsxProcess = tsx({\n\t\t\t\targs: ['--interactive'],\n\t\t\t});\n\n\t\t\tawait processInteract(\n\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t[\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('> ')) {\n\t\t\t\t\t\t\ttsxProcess.stdin!.write('(\\r');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('... ')) {\n\t\t\t\t\t\t\ttsxProcess.stdin!.write('1\\r');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('... ')) {\n\t\t\t\t\t\t\ttsxProcess.stdin!.write(')\\r');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdata => data.includes('1'),\n\t\t\t\t],\n\t\t\t\t5000,\n\t\t\t);\n\n\t\t\ttsxProcess.kill();\n\t\t}, 40_000);\n\n\t\ttest('errors on import statement', async () => {\n\t\t\tconst tsxProcess = tsx({\n\t\t\t\targs: ['--interactive'],\n\t\t\t});\n\n\t\t\tawait processInteract(\n\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t[\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('> ')) {\n\t\t\t\t\t\t\ttsxProcess.stdin!.write('import fs from \"fs\"\\r');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdata => data.includes('SyntaxError: Cannot use import statement'),\n\t\t\t\t],\n\t\t\t\t5000,\n\t\t\t);\n\n\t\t\ttsxProcess.kill();\n\t\t}, 40_000);\n\t});\n});\n"
  },
  {
    "path": "tests/specs/smoke.ts",
    "content": "import path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { testSuite, expect } from 'manten';\nimport { createFixture } from 'fs-fixture';\nimport outdent from 'outdent';\nimport type { NodeApis } from '../utils/tsx.js';\nimport { hasCoverageSourcesContent } from '../utils/coverage-sources-content.js';\nimport { isWindows } from '../utils/is-windows.js';\nimport { files, createPackageJson } from '../fixtures.js';\nimport { packageTypes } from '../utils/package-types.js';\n\nconst wasmPath = path.resolve('tests/fixtures/test.wasm');\nconst wasmPathUrl = pathToFileURL(wasmPath).toString();\n\nexport default testSuite(async ({ describe }, { tsx, supports, version }: NodeApis) => {\n\tdescribe('Smoke', ({ describe, test }) => {\n\t\tfor (const packageType of packageTypes) {\n\t\t\tconst isCommonJs = packageType !== 'module';\n\n\t\t\tdescribe(`package type: ${packageType ?? 'undefined'}`, ({ test }) => {\n\t\t\t\ttest('from .js', async ({ onTestFail }) => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'package.json': createPackageJson(packageType ? { type: packageType } : {}),\n\t\t\t\t\t\t'import-from-js.js': outdent`\n\t\t\t\t\t\timport assert from 'assert';\n\t\t\t\t\t\timport { expectErrors } from 'expect-errors';\n\n\t\t\t\t\t\tconst shouldntAffectFile = \\`\n\t\t\t\t\t\t//# sourceMappingURL=\\`;\n\t\t\t\t\t\t//# sourceMappingURL=shouldnt affect the file\n\n\t\t\t\t\t\t// node: prefix\n\t\t\t\t\t\timport 'node:fs';\n\n\t\t\t\t\t\timport * as pkgCommonjs from 'pkg-commonjs';\n\n\t\t\t\t\t\t// Named exports from CommonJS\n\t\t\t\t\t\timport { cjsJs } from 'pkg-commonjs/cjs';\n\n\t\t\t\t\t\timport * as pkgModule from 'pkg-module';\n\t\t\t\t\t\timport 'pkg-module/index';\n\t\t\t\t\t\timport 'pkg-module/empty-export'; // implicit directory & extension\n\n\t\t\t\t\t\timport 'pkg-exports/file';\n\n\t\t\t\t\t\t// .js in esm syntax\n\t\t\t\t\t\timport * as js from './js/index.js';\n\t\t\t\t\t\timport './js/index.js?query=123';\n\t\t\t\t\t\timport '@/js/index.js?query=123';\n\t\t\t\t\t\timport './js/index';\n\t\t\t\t\t\timport '@/js/index';\n\t\t\t\t\t\timport './js/';\n\t\t\t\t\t\timport '@/js/';\n\n\t\t\t\t\t\t// No double .default.default in Dynamic Import\n\t\t\t\t\t\timport/* comment */('./js/index.js').then(m => {\n\t\t\t\t\t\t\tif (typeof m.default === 'object') {\n\t\t\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\t\t\t!('default' in m.default),\n\t\t\t\t\t\t\t\t\t'Should not have double .default.default in Dynamic Import',\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst importWorksInEval = async () => await import ('./js/index.js');\n\t\t\t\t\t\t(0, eval)(importWorksInEval.toString())();\n\n\t\t\t\t\t\t// .json\n\t\t\t\t\t\timport * as json from './json/index.json';\n\t\t\t\t\t\timport './json/index';\n\t\t\t\t\t\timport '@/json/index';\n\t\t\t\t\t\timport './json/';\n\t\t\t\t\t\timport '@/json/';\n\n\t\t\t\t\t\t// .cjs\n\t\t\t\t\t\timport * as cjs from './cjs/index.cjs';\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t[() => import ('./cjs/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t[() => import ('./cjs/'), 'Cannot find module'],\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs\n\t\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\t[() => require('./cjs/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t[() => require('./cjs/'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// .mjs\n\t\t\t\t\t\timport * as mjs from './mjs/index.mjs';\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t[() => import ('./mjs/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t[() => import ('./mjs/'), 'Cannot find module'],\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs && !supports.requireEsm\n\t\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\t[() => require('./mjs/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t[() => require('./mjs/'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Is TS loadable here?\n\t\t\t\t\t\t// Import jsx?\n\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t// External source maps\n\t\t\t\t\t\t\t[() => import ('./file-with-sourcemap.js'), 'asdf.js:30:7'],\n\n\t\t\t\t\t\t\t// Unsupported files\n\t\t\t\t\t\t\t[() => import ('./file.txt'), 'Unknown file extension'],\n\t\t\t\t\t\t\t[() => import (${JSON.stringify(wasmPathUrl)}), 'Unknown file extension'],\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs\n\t\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\t[() => require('./file.txt'), 'hello is not defined'],\n\t\t\t\t\t\t\t\t\t[() => require(${JSON.stringify(wasmPath)}), 'Invalid or unexpected token'],\n\t\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs\n\t\t\t\t\t\t\t\t\t? '[() => require(\\'./broken-syntax\\'), \\'Transform failed\\'],'\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t[() => import ('./broken-syntax'), 'Transform failed'],\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconsole.log(JSON.stringify({\n\t\t\t\t\t\t\t'import.meta.url': import.meta.url,\n\t\t\t\t\t\t\tjs,\n\t\t\t\t\t\t\tjson,\n\t\t\t\t\t\t\tcjs,\n\t\t\t\t\t\t\tmjs,\n\t\t\t\t\t\t\tpkgCommonjs,\n\t\t\t\t\t\t\tpkgModule,\n\t\t\t\t\t\t}));\n\n\t\t\t\t\t\t// Could .js import TS files?\n\n\t\t\t\t\t\t// Comment at EOF: could be a sourcemap declaration. Edge case for inserting functions here\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t...files,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst p = await tsx(['import-from-js.js'], fixture.path);\n\t\t\t\t\tonTestFail((error) => {\n\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t\tconsole.log(p);\n\t\t\t\t\t});\n\n\t\t\t\t\texpect(p.failed).toBe(false);\n\t\t\t\t\texpect(p.stdout).toMatch(`\"import.meta.url\":\"${pathToFileURL(fixture.getPath('import-from-js.js'))}\"`);\n\t\t\t\t\texpect(p.stdout).toMatch(`\"js\":{\"cjsContext\":${isCommonJs},\"default\":1,\"named\":2}`);\n\t\t\t\t\texpect(p.stdout).toMatch('\"json\":{\"default\":{\"loaded-file\":\"json\"},\"loaded-file\":\"json\"}');\n\t\t\t\t\texpect(p.stdout).toMatch('\"cjs\":{\"default\":{\"named\":\"named\"},\"named\":\"named\"}');\n\t\t\t\t\texpect(p.stdout).toMatch('\"pkgModule\":{\"default\":1,\"named\":2}');\n\t\t\t\t\tif (isCommonJs) {\n\t\t\t\t\t\texpect(p.stdout).toMatch('\"pkgCommonjs\":{\"default\":1,\"named\":2}');\n\n\t\t\t\t\t\texpect(p.stdout).toMatch(/\\{\"importMetaUrl\":\"file:\\/\\/\\/.+?\\/js\\/index\\.js\",\"__filename\":\".+?index\\.js\"\\}/);\n\t\t\t\t\t\texpect(p.stdout).toMatch(/\\{\"importMetaUrl\":\"file:\\/\\/\\/.+?\\/js\\/index\\.js\\?query=123\",\"__filename\":\".+?index\\.js\"\\}/);\n\t\t\t\t\t} else {\n\t\t\t\t\t\texpect(p.stdout).toMatch(\n\t\t\t\t\t\t\tsupports.cjsInterop\n\t\t\t\t\t\t\t\t? '\"pkgCommonjs\":{\"default\":{\"default\":1,\"named\":2},\"named\":2}'\n\t\t\t\t\t\t\t\t: '\"pkgCommonjs\":{\"default\":{\"default\":1,\"named\":2}}',\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\texpect(p.stdout).toMatch(/\\{\"importMetaUrl\":\"file:\\/\\/\\/.+?\\/js\\/index\\.js\"\\}/);\n\t\t\t\t\t\texpect(p.stdout).toMatch(/\\{\"importMetaUrl\":\"file:\\/\\/\\/.+?\\/js\\/index\\.js\\?query=123\"\\}/);\n\t\t\t\t\t}\n\n\t\t\t\t\t// By \"require()\"ing an ESM file, it forces it to be compiled in a CJS context\n\t\t\t\t\texpect(p.stdout).toMatch(`\"mjs\":{\"mjsHasCjsContext\":${isCommonJs}}`);\n\n\t\t\t\t\texpect(p.stderr).toBe('');\n\t\t\t\t});\n\n\t\t\t\ttest('from .ts', async ({ onTestFail }) => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'package.json': createPackageJson(packageType ? { type: packageType } : {}),\n\n\t\t\t\t\t\t'import-from-ts.ts': ({ fixturePath }) => outdent`\n\t\t\t\t\t\timport assert from 'assert';\n\t\t\t\t\t\timport { expectErrors } from 'expect-errors';\n\n\t\t\t\t\t\tconst shouldntAffectFile = \\`\n\t\t\t\t\t\t//# sourceMappingURL=\\`;\n\t\t\t\t\t\t//# sourceMappingURL=shouldnt affect the file\n\n\t\t\t\t\t\t// node: prefix\n\t\t\t\t\t\timport 'node:fs';\n\n\t\t\t\t\t\t// Dependencies\n\t\t\t\t\t\timport * as pkgCommonjs from 'pkg-commonjs';\n\t\t\t\t\t\timport * as pkgModule from 'pkg-module';\n\t\t\t\t\t\timport 'pkg-module/index';\n\n\t\t\t\t\t\timport 'pkg-exports/file';\n\n\t\t\t\t\t\t// Resolving TS files in dependencies (e.g. implicit extensions & export maps)\n\t\t\t\t\t\timport 'pkg-commonjs/ts.js';\n\t\t\t\t\t\timport 'pkg-module/ts.js';\n\n\t\t\t\t\t\t// Named exports from CommonJS\n\t\t\t\t\t\timport { cjsJs } from 'pkg-commonjs/cjs';\n\n\t\t\t\t\t\t// .js in esm syntax\n\t\t\t\t\t\timport * as js from './js/index.js';\n\t\t\t\t\t\timport './js/index.js?query=123';\n\t\t\t\t\t\timport '@/js/index.js?query=123';\n\t\t\t\t\t\timport './js/index';\n\t\t\t\t\t\timport './js/';\n\n\t\t\t\t\t\t// absolute path\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tisWindows\n\t\t\t\t\t\t\t\t? ''\n\t\t\t\t\t\t\t\t: `import ${JSON.stringify(path.join(fixturePath, 'js/index.js'))};`\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// absolute file url\n\t\t\t\t\t\timport ${JSON.stringify(\n\t\t\t\t\t\t\tnew URL('js/index.js', pathToFileURL(fixturePath)).toString(),\n\t\t\t\t\t\t)};\n\n\t\t\t\t\t\t// No double .default.default in Dynamic Import\n\t\t\t\t\t\timport/* comment */('./js/index.js').then(m => {\n\t\t\t\t\t\t\tif (typeof m.default === 'object') {\n\t\t\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\t\t\t!('default' in m.default),\n\t\t\t\t\t\t\t\t\t'Should not have double .default.default in Dynamic Import',\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// .json\n\t\t\t\t\t\timport * as json from './json/index.json';\n\t\t\t\t\t\timport './json/index';\n\t\t\t\t\t\timport './json/';\n\n\t\t\t\t\t\t// .cjs\n\t\t\t\t\t\timport * as cjs from './cjs/index.cjs';\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t[() => import ('./cjs/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t[() => import ('./cjs/'), 'Cannot find module'],\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs\n\t\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\t[() => require('./cjs/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t[() => require('./cjs/'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// .mjs\n\t\t\t\t\t\timport * as mjs from './mjs/index.mjs';\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t[() => import ('./mjs/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t[() => import ('./mjs/'), 'Cannot find module'],\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs && !supports.requireEsm\n\t\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\t[() => require('./mjs/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t[() => require('./mjs/'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// .ts\n\t\t\t\t\t\timport './ts/index.ts';\n\t\t\t\t\t\timport './ts/index.js';\n\t\t\t\t\t\timport '@/ts/index.js';\n\t\t\t\t\t\timport './ts/index.jsx';\n\t\t\t\t\t\timport './ts/index';\n\t\t\t\t\t\timport '@/ts/index';\n\t\t\t\t\t\timport './ts/';\n\t\t\t\t\t\timport '@/ts/';\n\t\t\t\t\t\timport './ts/period.in.name';\n\t\t\t\t\t\timport '@/ts/period.in.name';\n\t\t\t\t\t\timport './ts/dotdot';\n\t\t\t\t\t\timport './ts/dotdot/dotdot';\n\n\t\t\t\t\t\t// .jsx\n\t\t\t\t\t\timport * as jsx from './jsx/index.jsx';\n\t\t\t\t\t\timport './jsx/index.js';\n\t\t\t\t\t\timport '@/jsx/index.js';\n\t\t\t\t\t\timport './jsx/index';\n\t\t\t\t\t\timport '@/jsx/index';\n\t\t\t\t\t\timport './jsx/';\n\t\t\t\t\t\timport '@/jsx/';\n\n\t\t\t\t\t\t// .tsx\n\t\t\t\t\t\timport './tsx/index.tsx';\n\t\t\t\t\t\timport './tsx/index.js';\n\t\t\t\t\t\timport './tsx/index.jsx';\n\t\t\t\t\t\timport '@/tsx/index.jsx';\n\t\t\t\t\t\timport './tsx/index';\n\t\t\t\t\t\timport '@/tsx/index';\n\t\t\t\t\t\timport './tsx/';\n\t\t\t\t\t\timport '@/tsx/';\n\n\t\t\t\t\t\t// .cts\n\t\t\t\t\t\timport './cts/index.cjs';\n\t\t\t\t\t\timport '@/cts/index.cjs';\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t// TODO:\n\t\t\t\t\t\t\t// [() => import ('./cts/index.cts'), 'Cannot find module'],\n\t\t\t\t\t\t\t[() => import ('./cts/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t[() => import ('./cts/'), 'Cannot find module'],\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs\n\t\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\t[() => require('./cts/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t[() => require('./cts/'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// Loading via Node arg should not work via .cjs but with .cts\n\n\t\t\t\t\t\t// .mts\n\t\t\t\t\t\timport './mts/index.mjs';\n\t\t\t\t\t\timport '@/mts/index.mjs';\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t// TODO:\n\t\t\t\t\t\t\t// [() => import ('./mts/index.mts'), 'Cannot find module'],\n\t\t\t\t\t\t\t[() => import ('./mts/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t[() => import ('./mts/'), 'Cannot find module'],\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs\n\t\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\t[() => require('./mts/index'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t[() => require('./mts/'), 'Cannot find module'],\n\t\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// Loading via Node arg should not work via .mjs but with .mts\n\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t// External source maps\n\t\t\t\t\t\t\t[() => import ('./file-with-sourcemap.js'), 'asdf.js:30:7'],\n\n\t\t\t\t\t\t\t// Unsupported files\n\t\t\t\t\t\t\t[() => import ('./file.txt'), 'Unknown file extension'],\n\t\t\t\t\t\t\t[() => import (${JSON.stringify(wasmPathUrl)}), 'Unknown file extension'],\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs\n\t\t\t\t\t\t\t\t\t? `\n\t\t\t\t\t\t\t\t\t[() => require('./file.txt'), 'hello is not defined'],\n\t\t\t\t\t\t\t\t\t[() => require(${JSON.stringify(wasmPath)}), 'Invalid or unexpected token'],\n\t\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\tisCommonJs\n\t\t\t\t\t\t\t\t\t? '[() => require(\\'./broken-syntax\\'), \\'Transform failed\\'],'\n\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t[() => import ('./broken-syntax'), 'Transform failed'],\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconsole.log(JSON.stringify({\n\t\t\t\t\t\t\t'import.meta.url': import.meta.url,\n\t\t\t\t\t\t\tjs,\n\t\t\t\t\t\t\tjson,\n\t\t\t\t\t\t\tjsx,\n\t\t\t\t\t\t\tcjs,\n\t\t\t\t\t\t\tmjs,\n\t\t\t\t\t\t\tpkgCommonjs,\n\t\t\t\t\t\t\tpkgModule,\n\t\t\t\t\t\t}));\n\n\t\t\t\t\t\t// Comment at EOF: could be a sourcemap declaration. Edge case for inserting functions here\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t...files,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst p = await tsx(['import-from-ts.ts'], {\n\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\tenv: {\n\t\t\t\t\t\t\tNODE_V8_COVERAGE: 'coverage',\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\n\t\t\t\t\tonTestFail((error) => {\n\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t\tconsole.log(p);\n\t\t\t\t\t});\n\t\t\t\t\texpect(p.failed).toBe(false);\n\t\t\t\t\texpect(p.stdout).toMatch(`\"import.meta.url\":\"${pathToFileURL(fixture.getPath('import-from-ts.ts'))}\"`);\n\t\t\t\t\texpect(p.stdout).toMatch(`\"js\":{\"cjsContext\":${isCommonJs},\"default\":1,\"named\":2}`);\n\t\t\t\t\texpect(p.stdout).toMatch('\"json\":{\"default\":{\"loaded-file\":\"json\"},\"loaded-file\":\"json\"}');\n\t\t\t\t\texpect(p.stdout).toMatch('\"cjs\":{\"default\":{\"named\":\"named\"},\"named\":\"named\"}');\n\t\t\t\t\texpect(p.stdout).toMatch(`\"jsx\":{\"cjsContext\":${isCommonJs},\"jsx\":[null,null,[\"div\",null,\"JSX\"]]}`);\n\t\t\t\t\texpect(p.stdout).toMatch('\"pkgModule\":{\"default\":1,\"named\":2}');\n\t\t\t\t\tif (isCommonJs) {\n\t\t\t\t\t\texpect(p.stdout).toMatch('\"pkgCommonjs\":{\"default\":1,\"named\":2}');\n\n\t\t\t\t\t\texpect(p.stdout).toMatch(/\\{\"importMetaUrl\":\"file:\\/\\/\\/.+?\\/js\\/index\\.js\",\"__filename\":\".+?index\\.js\"\\}/);\n\t\t\t\t\t\texpect(p.stdout).toMatch(/\\{\"importMetaUrl\":\"file:\\/\\/\\/.+?\\/js\\/index\\.js\\?query=123\",\"__filename\":\".+?index\\.js\"\\}/);\n\t\t\t\t\t} else {\n\t\t\t\t\t\texpect(p.stdout).toMatch(\n\t\t\t\t\t\t\tsupports.cjsInterop\n\t\t\t\t\t\t\t\t? '\"pkgCommonjs\":{\"default\":{\"default\":1,\"named\":2},\"named\":2}'\n\t\t\t\t\t\t\t\t: '\"pkgCommonjs\":{\"default\":{\"default\":1,\"named\":2}}',\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\texpect(p.stdout).toMatch(/\\{\"importMetaUrl\":\"file:\\/\\/\\/.+?\\/js\\/index\\.js\"\\}/);\n\t\t\t\t\t\texpect(p.stdout).toMatch(/\\{\"importMetaUrl\":\"file:\\/\\/\\/.+?\\/js\\/index\\.js\\?query=123\"\\}/);\n\t\t\t\t\t}\n\n\t\t\t\t\t// By \"require()\"ing an ESM file, it forces it to be compiled in a CJS context\n\t\t\t\t\texpect(p.stdout).toMatch(`\"mjs\":{\"mjsHasCjsContext\":${isCommonJs}}`);\n\t\t\t\t\texpect(p.stderr).toBe('');\n\n\t\t\t\t\tconst coverageDirectory = fixture.getPath('coverage');\n\t\t\t\t\tconst coverageSourceMapCache = await hasCoverageSourcesContent(coverageDirectory);\n\t\t\t\t\texpect(coverageSourceMapCache).toBe(true);\n\t\t\t\t});\n\n\t\t\t\ttest('resolve ts in exports', async () => {\n\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t'package.json': createPackageJson(packageType ? { type: packageType } : {}),\n\t\t\t\t\t\t'index.ts': `\n\t\t\t\t\t\timport A from 'pkg'\n\t\t\t\t\t\tconsole.log(A satisfies 2)\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t'node_modules/pkg': {\n\t\t\t\t\t\t\t'package.json': createPackageJson({\n\t\t\t\t\t\t\t\tname: 'pkg',\n\t\t\t\t\t\t\t\texports: './test.js',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t'test.ts': 'export default 1',\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\n\t\t\t\t\tconst p = await tsx(['index.ts'], {\n\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t});\n\t\t\t\t\texpect(p.failed).toBe(false);\n\t\t\t\t});\n\n\t\t\t\t/**\n\t\t\t\t * Node v18 has a bug:\n\t\t\t\t * Error [ERR_INTERNAL_ASSERTION]:\n\t\t\t\t * \tCode: ERR_MODULE_NOT_FOUND; The provided arguments length (2) does\n\t\t\t\t *  not match the required ones (3)\n\t\t\t\t */\n\t\t\t\tif (!version.startsWith('18.')) {\n\t\t\t\t\ttest('resolve ts in main', async ({ onTestFail }) => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson(packageType ? { type: packageType } : {}),\n\t\t\t\t\t\t\t'index.ts': `\n\t\t\t\t\t\t\timport A from 'pkg'\n\t\t\t\t\t\t\tconsole.log(A satisfies 2);\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t\t'node_modules/pkg': {\n\t\t\t\t\t\t\t\t'package.json': createPackageJson({\n\t\t\t\t\t\t\t\t\tname: 'pkg',\n\t\t\t\t\t\t\t\t\tmain: './test.js',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t'test.ts': 'export default 1',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst p = await tsx(['index.ts'], {\n\t\t\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tonTestFail(() => {\n\t\t\t\t\t\t\tconsole.log(p);\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(p.failed).toBe(false);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// https://github.com/privatenumber/tsx/issues/651\n\t\ttest('resolves same relative path from CJS loaded by ESM', async ({ onTestFail }) => {\n\t\t\tawait using fixture = await createFixture({\n\t\t\t\t'package.json': createPackageJson({ type: 'commonjs' }),\n\t\t\t\ta: {\n\t\t\t\t\t'index.ts': `\n\t\t\t\t\timport { value } from './value.js';\n\n\t\t\t\t\tif (value !== 1) {\n\t\t\t\t\t\tthrow new Error('Unexpected value');\n\t\t\t\t\t}\n\t\t\t\t\t`,\n\t\t\t\t\t'value.js': 'export const value = 1;',\n\t\t\t\t},\n\t\t\t\tb: {\n\t\t\t\t\t'index.ts': `\n\t\t\t\t\timport { value } from './value.js';\n\n\t\t\t\t\tif (value !== 2) {\n\t\t\t\t\t\tthrow new Error('Unexpected value');\n\t\t\t\t\t}\n\t\t\t\t\t`,\n\t\t\t\t\t'value.js': 'export const value = 2;',\n\t\t\t\t},\n\t\t\t\t'index.mjs': `\n\t\t\t\timport './a/index.js';\n\t\t\t\timport './b/index.js';\n\t\t\t\t`,\n\t\t\t});\n\n\t\t\tconst p = await tsx(['index.mjs'], {\n\t\t\t\tcwd: fixture.path,\n\t\t\t});\n\t\t\tonTestFail(() => {\n\t\t\t\tconsole.log(p);\n\t\t\t});\n\t\t\texpect(p.failed).toBe(false);\n\t\t});\n\n\t\tif (supports.cjsInterop) {\n\t\t\ttest('mjs file can import named export from fake ESM even with --jitless', async ({ onTestFail }) => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'esm-in-cjs.js': 'export const value = 1;',\n\t\t\t\t\t'index.mjs': `\n\t\t\t\t\timport { value } from './esm-in-cjs.js';\n\t\t\t\t\tconsole.log(value);\n\t\t\t\t\t`,\n\t\t\t\t});\n\n\t\t\t\tconst p = await tsx(['--jitless', 'index.mjs'], {\n\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t});\n\t\t\t\tonTestFail(() => {\n\t\t\t\t\tconsole.log(p);\n\t\t\t\t});\n\t\t\t\texpect(p.failed).toBe(false);\n\t\t\t});\n\t\t}\n\n\t\t// https://github.com/privatenumber/tsx/issues/727\n\t\tdescribe('CJS & ESM race condition', ({ test }) => {\n\t\t\ttest('explicit extension', async ({ onTestFail }) => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'index.mjs': `\n\t\t\t\t\timport './require.cjs'\n\t\t\t\t\timport './import.mjs'\n\t\t\t\t\t`,\n\t\t\t\t\t'import.mjs': 'import \"./cjs.cjs\"',\n\t\t\t\t\t'require.cjs': `\n\t\t\t\t\tif (require(\"./cjs.cjs\") !== 123) {\n\t\t\t\t\t\tthrow new Error('CJS import failed');\n\t\t\t\t\t}\n\t\t\t\t\t`,\n\t\t\t\t\t'cjs.cjs': `\n\t\t\t\t\tmodule.exports = 123\n\t\t\t\t\t`,\n\t\t\t\t});\n\n\t\t\t\tconst p = await tsx(['index.mjs'], {\n\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t});\n\t\t\t\tonTestFail(() => {\n\t\t\t\t\tconsole.log(p);\n\t\t\t\t});\n\t\t\t\texpect(p.failed).toBe(false);\n\t\t\t});\n\n\t\t\ttest('implicit extension', async ({ onTestFail }) => {\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t'index.mjs': `\n\t\t\t\t\timport './require/index.js'\n\t\t\t\t\timport './import/index.js'\n\t\t\t\t\t`,\n\t\t\t\t\timport: {\n\t\t\t\t\t\t'package.json': createPackageJson({ type: 'module' }),\n\t\t\t\t\t\t'index.js': 'import \"../cjs.js\"',\n\t\t\t\t\t},\n\t\t\t\t\trequire: {\n\t\t\t\t\t\t'package.json': createPackageJson({ type: 'commonjs' }),\n\t\t\t\t\t\t'index.js': `\n\t\t\t\t\t\tif (require(\"../cjs.js\") !== 123) {\n\t\t\t\t\t\t\tthrow new Error('CJS import failed');\n\t\t\t\t\t\t}\n\t\t\t\t\t\t`,\n\t\t\t\t\t},\n\t\t\t\t\t'cjs.js': `\n\t\t\t\t\tmodule.exports = 123\n\t\t\t\t\t`,\n\t\t\t\t});\n\n\t\t\t\tconst p = await tsx(['index.mjs'], {\n\t\t\t\t\tcwd: fixture.path,\n\t\t\t\t});\n\t\t\t\tonTestFail(() => {\n\t\t\t\t\tconsole.log(p);\n\t\t\t\t});\n\t\t\t\texpect(p.failed).toBe(false);\n\t\t\t});\n\t\t});\n\n\t\t// https://github.com/privatenumber/tsx/issues/722\n\t\ttest('handles require loop', async ({ onTestFail }) => {\n\t\t\tawait using fixture = await createFixture({\n\t\t\t\t'index.ts': 'require(\"./a.js\")',\n\t\t\t\t'a.js': 'require(\"./b.js\")',\n\t\t\t\t'b.js': 'require(\"./a.js\")',\n\t\t\t});\n\n\t\t\tconst p = await tsx(['index.ts'], {\n\t\t\t\tcwd: fixture.path,\n\t\t\t});\n\t\t\tonTestFail(() => {\n\t\t\t\tconsole.log(p);\n\t\t\t});\n\t\t\texpect(p.failed).toBe(false);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "tests/specs/transform.ts",
    "content": "import { testSuite, expect } from 'manten';\nimport { createFsRequire } from 'fs-require';\nimport { Volume } from 'memfs';\nimport outdent from 'outdent';\nimport { transform, transformSync } from '../../src/utils/transform/index.js';\n\nconst base64Module = (code: string) => `data:text/javascript;base64,${Buffer.from(code).toString('base64')}`;\n\nconst fixtures = {\n\tts: outdent`\n\tconst __filename = 'filename';\n\tconst __dirname = 'dirname';\n\ttry {\n\t\tconst unusedVariable1 = 1;\n\t} catch (unusedError) {\n\t\tconst unusedVariable2 = 2;\n\t}\n\texport default 'default value' as string;\n\texport const named: string = 'named';\n\texport const functionName: string = (function named() {}).name;\n\texport const url = import.meta.url;\n\t`,\n\n\tesm: outdent`\n\tconst __filename = 'filename';\n\tconst __dirname = 'dirname';\n\ttry {\n\t\tconst unusedVariable1 = 1;\n\t} catch (unusedError) {\n\t\tconst unusedVariable2 = 2;\n\t}\n\n\texport default 'default value';\n\texport const named = 'named';\n\texport const functionName = (function named() {}).name;\n\texport const url = import.meta.url;\n\t`,\n};\n\nexport default testSuite(({ describe }) => {\n\tdescribe('transform', ({ describe }) => {\n\t\tdescribe('sync', ({ test }) => {\n\t\t\ttest('transforms ESM to CJS', () => {\n\t\t\t\tconst transformed = transformSync(\n\t\t\t\t\tfixtures.esm,\n\t\t\t\t\t'file.js',\n\t\t\t\t\t{ format: 'cjs' },\n\t\t\t\t);\n\n\t\t\t\t// For debuggers\n\t\t\t\texpect(transformed.code).toMatch('unusedVariable1');\n\t\t\t\texpect(transformed.code).toMatch('unusedVariable2');\n\n\t\t\t\tconst fsRequire = createFsRequire(Volume.fromJSON({\n\t\t\t\t\t'/file.js': transformed.code,\n\t\t\t\t}));\n\n\t\t\t\texpect(fsRequire('/file.js')).toStrictEqual({\n\t\t\t\t\tdefault: 'default value',\n\t\t\t\t\tfunctionName: 'named',\n\t\t\t\t\tnamed: 'named',\n\t\t\t\t\turl: expect.stringMatching(/^file:\\/\\/\\/.*\\/file.js$/),\n\t\t\t\t});\n\t\t\t});\n\n\t\t\ttest('dynamic import', () => {\n\t\t\t\tconst dynamicImport = transformSync(\n\t\t\t\t\t'import((0, _url.pathToFileURL)(path).href)',\n\t\t\t\t\t'file.js',\n\t\t\t\t\t{ format: 'cjs' },\n\t\t\t\t);\n\n\t\t\t\texpect(dynamicImport.code).toMatch('.href).then');\n\t\t\t});\n\n\t\t\ttest('sourcemap file', () => {\n\t\t\t\tconst fileName = 'file.mts';\n\t\t\t\tconst transformed = transformSync(\n\t\t\t\t\tfixtures.ts,\n\t\t\t\t\tfileName,\n\t\t\t\t\t{ format: 'esm' },\n\t\t\t\t);\n\n\t\t\t\texpect(transformed.map).not.toBe('');\n\n\t\t\t\tconst { map } = transformed;\n\t\t\t\tif (typeof map !== 'string') {\n\t\t\t\t\texpect(map.sources.length).toBe(1);\n\t\t\t\t\texpect(map.sources[0]).toBe(fileName);\n\t\t\t\t\texpect(map.names).toStrictEqual(['named']);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttest('quotes in file path', () => {\n\t\t\t\tconst fileName = '\\'\"name.mts';\n\t\t\t\tconst transformed = transformSync(\n\t\t\t\t\tfixtures.ts,\n\t\t\t\t\tfileName,\n\t\t\t\t\t{ format: 'esm' },\n\t\t\t\t);\n\n\t\t\t\texpect(transformed.map).not.toBe('');\n\n\t\t\t\tconst { map } = transformed;\n\t\t\t\tif (typeof map !== 'string') {\n\t\t\t\t\texpect(map.sources.length).toBe(1);\n\t\t\t\t\texpect(map.sources[0]).toBe(fileName);\n\t\t\t\t\texpect(map.names).toStrictEqual(['named']);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\tdescribe('async', ({ test }) => {\n\t\t\ttest('transforms TS to ESM', async () => {\n\t\t\t\tconst transformed = await transform(\n\t\t\t\t\tfixtures.ts,\n\t\t\t\t\t'file.ts',\n\t\t\t\t\t{ format: 'esm' },\n\t\t\t\t);\n\n\t\t\t\t// For debuggers\n\t\t\t\texpect(transformed.code).toMatch('unusedVariable1');\n\t\t\t\texpect(transformed.code).toMatch('unusedVariable2');\n\n\t\t\t\tconst imported = await import(base64Module(transformed.code));\n\t\t\t\texpect({ ...imported }).toStrictEqual({\n\t\t\t\t\tdefault: 'default value',\n\t\t\t\t\tfunctionName: 'named',\n\t\t\t\t\tnamed: 'named',\n\t\t\t\t\turl: expect.stringMatching(/^data:text\\/javascript;base64,.+$/),\n\t\t\t\t});\n\t\t\t});\n\n\t\t\ttest('sourcemap file', async () => {\n\t\t\t\tconst fileName = 'file.cts';\n\t\t\t\tconst transformed = await transform(\n\t\t\t\t\tfixtures.ts,\n\t\t\t\t\tfileName,\n\t\t\t\t\t{ format: 'esm' },\n\t\t\t\t);\n\n\t\t\t\texpect(transformed.map).not.toBe('');\n\n\t\t\t\tconst { map } = transformed;\n\t\t\t\tif (typeof map !== 'string') {\n\t\t\t\t\texpect(map.sources.length).toBe(1);\n\t\t\t\t\texpect(map.sources[0]).toBe(fileName);\n\t\t\t\t\texpect(map.names).toStrictEqual(['named']);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "tests/specs/tsconfig.ts",
    "content": "import { testSuite, expect } from 'manten';\nimport { createFixture } from 'fs-fixture';\nimport type { NodeApis } from '../utils/tsx.js';\nimport {\n\texpectErrors, jsxCheck, createPackageJson, createTsconfig,\n} from '../fixtures.js';\nimport { packageTypes } from '../utils/package-types.js';\n\nexport default testSuite(async ({ describe }, { tsx }: NodeApis) => {\n\tdescribe('tsconfig', ({ describe }) => {\n\t\tfor (const packageType of packageTypes) {\n\t\t\tdescribe(`package type: ${packageType ?? 'undefined'}`, async ({ describe, onFinish }) => {\n\t\t\t\tconst fixture = await createFixture({\n\t\t\t\t\t...expectErrors,\n\n\t\t\t\t\t'package.json': createPackageJson(packageType ? { type: packageType } : {}),\n\n\t\t\t\t\t'tsconfig.json': createTsconfig({\n\t\t\t\t\t\tcompilerOptions: {\n\t\t\t\t\t\t\tjsxFactory: 'Array',\n\t\t\t\t\t\t\tjsxFragmentFactory: 'null',\n\t\t\t\t\t\t\tbaseUrl: '.',\n\t\t\t\t\t\t\tpaths: {\n\t\t\t\t\t\t\t\t'paths-exact-match': ['file'],\n\t\t\t\t\t\t\t\t'prefix/*': ['*'],\n\t\t\t\t\t\t\t\t'*/suffix': ['*'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\n\t\t\t\t\t'tsconfig-allowJs.json': createTsconfig({\n\t\t\t\t\t\textends: './tsconfig.json',\n\t\t\t\t\t\tcompilerOptions: {\n\t\t\t\t\t\t\tallowJs: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\n\t\t\t\t\t'tsconfig-broken.json': '{ asdf',\n\n\t\t\t\t\t'tsconfig-unresolvable.json': createTsconfig({\n\t\t\t\t\t\textends: 'doesnt-exist',\n\t\t\t\t\t}),\n\n\t\t\t\t\t'index.tsx': `\n\t\t\t\t\t${jsxCheck};\n\n\t\t\t\t\timport './jsx';\n\n\t\t\t\t\t// Resolves relative to baseUrl\n\t\t\t\t\timport 'file';\n\n\t\t\t\t\t// Resolves paths - exact match\n\t\t\t\t\timport 'paths-exact-match';\n\n\t\t\t\t\t// Resolves paths - prefix match\n\t\t\t\t\timport 'prefix/file';\n\n\t\t\t\t\t// Resolves paths - suffix match\n\t\t\t\t\timport 'file/suffix';\n\n\t\t\t\t\t// tsconfig should not apply to dependency\n\t\t\t\t\timport 'tsconfig-should-not-apply';\n\t\t\t\t\t`,\n\n\t\t\t\t\t'file.ts': '',\n\n\t\t\t\t\t'jsx.jsx': `\n\t\t\t\t\t// tsconfig not applied to jsx because allowJs is not set\n\t\t\t\t\timport { expectErrors } from 'expect-errors';\n\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t[() => ${jsxCheck}, 'React is not defined'],\n\n\t\t\t\t\t\t// These should throw unless allowJs is set\n\t\t\t\t\t\t// [() => import ('prefix/file'), \"Cannot find package 'prefix'\"],\n\t\t\t\t\t\t// [() => import ('paths-exact-match'), \"Cannot find package 'paths-exact-match'\"],\n\t\t\t\t\t\t// [() => import ('file'), \"Cannot find package 'file'\"],\n\t\t\t\t\t);\n\t\t\t\t\t`,\n\n\t\t\t\t\t'import-typescript-parent.js': `\n\t\t\t\t\timport './import-typescript-child.js';\n\t\t\t\t\t`,\n\n\t\t\t\t\t'import-typescript-child.ts': `\n\t\t\t\t\tconsole.log('imported');\n\t\t\t\t\t`,\n\n\t\t\t\t\t'node_modules/tsconfig-should-not-apply': {\n\t\t\t\t\t\t'package.json': createPackageJson({\n\t\t\t\t\t\t\texports: {\n\t\t\t\t\t\t\t\timport: './index.mjs',\n\t\t\t\t\t\t\t\tdefault: './index.cjs',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t'index.mjs': `\n\t\t\t\t\t\timport { expectErrors } from 'expect-errors';\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t[() => import ('prefix/file'), \"Cannot find package 'prefix'\"],\n\t\t\t\t\t\t\t[() => import ('paths-exact-match'), \"Cannot find package 'paths-exact-match'\"],\n\t\t\t\t\t\t\t[() => import ('file'), \"Cannot find package 'file'\"],\n\t\t\t\t\t\t);\n\t\t\t\t\t\t`,\n\t\t\t\t\t\t'index.cjs': `\n\t\t\t\t\t\tconst { expectErrors } = require('expect-errors');\n\t\t\t\t\t\texpectErrors(\n\t\t\t\t\t\t\t[() => require('prefix/file'), \"Cannot find module\"],\n\t\t\t\t\t\t\t[() => require('paths-exact-match'), \"Cannot find module\"],\n\t\t\t\t\t\t\t[() => require('file'), \"Cannot find module\"],\n\t\t\t\t\t\t);\n\t\t\t\t\t\t`,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tonFinish(async () => await fixture.rm());\n\n\t\t\t\tdescribe('detected tsconfig', ({ test }) => {\n\t\t\t\t\ttest('invalid tsconfig should be ignored', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson(packageType ? { type: packageType } : {}),\n\t\t\t\t\t\t\t'tsconfig.json': createTsconfig({\n\t\t\t\t\t\t\t\textends: 'doesnt-exist',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t'index.ts': '',\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst pTsconfig = await tsx(['index.ts'], fixture.path);\n\t\t\t\t\t\texpect(pTsconfig.failed).toBe(false);\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('tsconfig', async ({ onTestFail }) => {\n\t\t\t\t\t\tconst pTsconfig = await tsx(['index.tsx'], fixture.path);\n\t\t\t\t\t\tonTestFail((error) => {\n\t\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t\t\tconsole.log(pTsconfig);\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(pTsconfig.failed).toBe(false);\n\t\t\t\t\t\texpect(pTsconfig.stderr).toBe('');\n\t\t\t\t\t\texpect(pTsconfig.stdout).toBe('');\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tdescribe('custom tsconfig', ({ test }) => {\n\t\t\t\t\ttest('invalid tsconfig should error', async () => {\n\t\t\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t\t\t'package.json': createPackageJson(packageType ? { type: packageType } : {}),\n\t\t\t\t\t\t\t'tsconfig.json': createTsconfig({\n\t\t\t\t\t\t\t\textends: 'doesnt-exist',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t'index.ts': '',\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst pTsconfig = await tsx(['--tsconfig', 'tsconfig.json', 'index.ts'], fixture.path);\n\t\t\t\t\t\texpect(pTsconfig.failed).toBe(true);\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('custom tsconfig', async ({ onTestFail }) => {\n\t\t\t\t\t\tconst pTsconfigAllowJs = await tsx(['--tsconfig', 'tsconfig-allowJs.json', 'jsx.jsx'], fixture.path);\n\t\t\t\t\t\tonTestFail((error) => {\n\t\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t\t\tconsole.log(pTsconfigAllowJs);\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(pTsconfigAllowJs.failed).toBe(true);\n\t\t\t\t\t\texpect(pTsconfigAllowJs.stderr).toMatch('Error: No error thrown');\n\t\t\t\t\t\texpect(pTsconfigAllowJs.stdout).toBe('');\n\t\t\t\t\t});\n\n\t\t\t\t\ttest('allowJs in tsconfig.json', async ({ onTestFail }) => {\n\t\t\t\t\t\tconst pTsconfigAllowJs = await tsx(['--tsconfig', 'tsconfig-allowJs.json', 'import-typescript-parent.js'], fixture.path);\n\t\t\t\t\t\tonTestFail((error) => {\n\t\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t\t\tconsole.log(pTsconfigAllowJs);\n\t\t\t\t\t\t});\n\t\t\t\t\t\texpect(pTsconfigAllowJs.failed).toBe(false);\n\t\t\t\t\t\texpect(pTsconfigAllowJs.stderr).toBe('');\n\t\t\t\t\t\texpect(pTsconfigAllowJs.stdout).toBe('imported');\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t});\n});\n"
  },
  {
    "path": "tests/specs/watch.ts",
    "content": "import { setTimeout } from 'node:timers/promises';\nimport { testSuite, expect } from 'manten';\nimport { createFixture } from 'fs-fixture';\nimport type { NodeApis } from '../utils/tsx.js';\nimport { processInteract } from '../utils/process-interact.js';\nimport { createPackageJson } from '../fixtures.js';\n\nexport default testSuite(async ({ describe }, { tsx }: NodeApis) => {\n\tdescribe('watch', async ({ test, describe, onFinish }) => {\n\t\tconst fixture = await createFixture({\n\t\t\t// Unnecessary TS to test syntax\n\t\t\t'log-argv.ts': 'console.log(JSON.stringify(process.argv) as string)',\n\t\t});\n\t\tonFinish(async () => await fixture.rm());\n\n\t\ttest('require file path', async () => {\n\t\t\tconst tsxProcess = await tsx(['watch']);\n\t\t\texpect(tsxProcess.exitCode).toBe(1);\n\t\t\texpect(tsxProcess.stderr).toMatch('Error: Missing required parameter \"script path\"');\n\t\t});\n\n\t\tfor (const packageType of ['module', 'commonjs'] as const) {\n\t\t\ttest(`watch files for changes in ${packageType} package`, async ({ onTestFinish, onTestFail }) => {\n\t\t\t\tconst fixtureWatch = await createFixture({\n\t\t\t\t\t'package.json': createPackageJson({\n\t\t\t\t\t\ttype: packageType,\n\t\t\t\t\t}),\n\t\t\t\t\t'index.js': `\n\t\t\t\t\timport { value } from './value.js';\n\t\t\t\t\tconsole.log(value);\n\t\t\t\t\t`,\n\t\t\t\t\t'value.js': 'export const value = \\'hello world\\';',\n\t\t\t\t});\n\t\t\t\tonTestFinish(async () => await fixtureWatch.rm());\n\n\t\t\t\tconst tsxProcess = tsx(\n\t\t\t\t\t[\n\t\t\t\t\t\t'watch',\n\t\t\t\t\t\t'index.js',\n\t\t\t\t\t],\n\t\t\t\t\tfixtureWatch.path,\n\t\t\t\t);\n\n\t\t\t\tonTestFail(async () => {\n\t\t\t\t\tif (tsxProcess.exitCode === null) {\n\t\t\t\t\t\tconsole.log('Force killing hanging process\\n\\n');\n\t\t\t\t\t\ttsxProcess.kill('SIGKILL');\n\t\t\t\t\t\tconsole.log({\n\t\t\t\t\t\t\ttsxProcess: await tsxProcess,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait processInteract(\n\t\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t\t[\n\t\t\t\t\t\tasync (data) => {\n\t\t\t\t\t\t\tif (data.includes('hello world\\n')) {\n\t\t\t\t\t\t\t\tawait setTimeout(1000);\n\t\t\t\t\t\t\t\tfixtureWatch.writeFile('value.js', 'export const value = \\'goodbye world\\';');\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdata => data.includes('[tsx] change in ./value.js Rerunning...\\n'),\n\t\t\t\t\t\tdata => data.includes('goodbye world\\n'),\n\t\t\t\t\t],\n\t\t\t\t\t9000,\n\t\t\t\t);\n\n\t\t\t\ttsxProcess.kill();\n\n\t\t\t\tconst { all } = await tsxProcess;\n\t\t\t\texpect(all!.startsWith('hello world\\n')).toBe(true);\n\t\t\t}, 10_000);\n\t\t}\n\n\t\ttest('suppresses warnings & clear screen', async () => {\n\t\t\tconst tsxProcess = tsx(\n\t\t\t\t[\n\t\t\t\t\t'watch',\n\t\t\t\t\t'log-argv.ts',\n\t\t\t\t],\n\t\t\t\tfixture.path,\n\t\t\t);\n\n\t\t\tawait processInteract(\n\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t[\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('log-argv.ts')) {\n\t\t\t\t\t\t\ttsxProcess.stdin?.write('enter');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdata => data.includes('log-argv.ts'),\n\t\t\t\t],\n\t\t\t\t5000,\n\t\t\t);\n\n\t\t\ttsxProcess.kill();\n\n\t\t\tconst { all } = await tsxProcess;\n\t\t\texpect(all).not.toMatch('Warning');\n\t\t\texpect(all).toMatch('\\u001Bc');\n\t\t\texpect(all!.startsWith('[\"')).toBeTruthy();\n\t\t}, 10_000);\n\n\t\ttest('passes flags', async () => {\n\t\t\tconst tsxProcess = tsx(\n\t\t\t\t[\n\t\t\t\t\t'watch',\n\t\t\t\t\t'log-argv.ts',\n\t\t\t\t\t'--some-flag',\n\t\t\t\t],\n\t\t\t\tfixture.path,\n\t\t\t);\n\n\t\t\tawait processInteract(\n\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t[data => data.startsWith('[\"')],\n\t\t\t\t5000,\n\t\t\t);\n\n\t\t\ttsxProcess.kill();\n\n\t\t\tconst { all } = await tsxProcess;\n\t\t\texpect(all).toMatch('\"--some-flag\"');\n\t\t}, 10_000);\n\n\t\ttest('wait for exit', async ({ onTestFinish, onTestFail }) => {\n\t\t\tconst fixtureExit = await createFixture({\n\t\t\t\t'index.js': `\n\t\t\t\tconsole.log('start');\n\t\t\t\tconst sleepSync = (delay) => {\n\t\t\t\t\tconst waitTill = Date.now() + delay;\n\t\t\t\t\twhile (Date.now() < waitTill) {}\n\t\t\t\t};\n\t\t\t\tprocess.on('exit', () => {\n\t\t\t\t\tsleepSync(300);\n\t\t\t\t\tconsole.log('end');\n\t\t\t\t});\n\t\t\t\t`,\n\t\t\t});\n\n\t\t\tconst tsxProcess = tsx(\n\t\t\t\t[\n\t\t\t\t\t'watch',\n\t\t\t\t\t'index.js',\n\t\t\t\t],\n\t\t\t\tfixtureExit.path,\n\t\t\t);\n\n\t\t\tonTestFail(async () => {\n\t\t\t\tif (tsxProcess.exitCode === null) {\n\t\t\t\t\tconsole.log('Force killing hanging process\\n\\n');\n\t\t\t\t\ttsxProcess.kill('SIGKILL');\n\t\t\t\t\tconsole.log({\n\t\t\t\t\t\ttsxProcess: await tsxProcess,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tonTestFinish(async () => {\n\t\t\t\tawait fixtureExit.rm();\n\t\t\t});\n\n\t\t\tawait processInteract(\n\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t[\n\t\t\t\t\t(data) => {\n\t\t\t\t\t\tif (data.includes('start\\n')) {\n\t\t\t\t\t\t\ttsxProcess.stdin?.write('enter');\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdata => data.includes('end\\n'),\n\t\t\t\t],\n\t\t\t\t5000,\n\t\t\t);\n\n\t\t\ttsxProcess.kill();\n\n\t\t\tconst { all } = await tsxProcess;\n\t\t\texpect(all).toMatch(/start[\\s\\S]+end/);\n\t\t}, 10_000);\n\n\t\tdescribe('help', ({ test }) => {\n\t\t\ttest('shows help', async () => {\n\t\t\t\tconst tsxProcess = await tsx(['watch', '--help']);\n\n\t\t\t\texpect(tsxProcess.exitCode).toBe(0);\n\t\t\t\texpect(tsxProcess.stdout).toMatch('Run the script and watch for changes');\n\t\t\t\texpect(tsxProcess.stderr).toBe('');\n\t\t\t});\n\n\t\t\ttest('passes down --help to file', async ({ onTestFail }) => {\n\t\t\t\tconst tsxProcess = tsx(\n\t\t\t\t\t[\n\t\t\t\t\t\t'watch',\n\t\t\t\t\t\t'log-argv.ts',\n\t\t\t\t\t\t'--help',\n\t\t\t\t\t],\n\t\t\t\t\tfixture.path,\n\t\t\t\t);\n\n\t\t\t\tawait processInteract(\n\t\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t\t[data => data.startsWith('[\"')],\n\t\t\t\t\t5000,\n\t\t\t\t);\n\n\t\t\t\ttsxProcess.kill();\n\n\t\t\t\tconst { all } = await tsxProcess;\n\t\t\t\tonTestFail(() => {\n\t\t\t\t\tconsole.log(all);\n\t\t\t\t});\n\n\t\t\t\texpect(all).toMatch('\"--help\"');\n\t\t\t}, 10_000);\n\t\t});\n\n\t\tdescribe('include', ({ test }) => {\n\t\t\ttest('file path & glob', async () => {\n\t\t\t\tconst entryFile = 'index.js';\n\t\t\t\tconst fileA = 'file-a';\n\t\t\t\tconst fileB = 'directory/file-b';\n\t\t\t\tawait using fixture = await createFixture({\n\t\t\t\t\t[entryFile]: `\n\t\t\t\t\t\timport fs from 'fs/promises';\n\t\t\t\t\t\tPromise.all([\n\t\t\t\t\t\t\tfs.readFile('./${fileA}', 'utf8'),\n\t\t\t\t\t\t\tfs.readFile('./${fileB}', 'utf8')\n\t\t\t\t\t\t]).then(console.log, console.error);\n\t\t\t\t\t`.trim(),\n\t\t\t\t\t[fileA]: 'content-a',\n\t\t\t\t\t[fileB]: 'content-b',\n\t\t\t\t});\n\n\t\t\t\tconst tsxProcess = tsx(\n\t\t\t\t\t[\n\t\t\t\t\t\t'watch',\n\t\t\t\t\t\t'--clear-screen=false',\n\t\t\t\t\t\t`--include=${fileA}`,\n\t\t\t\t\t\t'--include=directory/*',\n\t\t\t\t\t\tentryFile,\n\t\t\t\t\t],\n\t\t\t\t\tfixture.path,\n\t\t\t\t);\n\n\t\t\t\tawait processInteract(\n\t\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t\t[\n\t\t\t\t\t\t(data) => {\n\t\t\t\t\t\t\tif (data.includes(\"'content-a', 'content-b'\")) {\n\t\t\t\t\t\t\t\tfixture.writeFile(fileA, 'update-a');\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t(data) => {\n\t\t\t\t\t\t\tif (data.includes(\"'update-a', 'content-b'\")) {\n\t\t\t\t\t\t\t\tfixture.writeFile(fileB, 'update-b');\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t(data) => {\n\t\t\t\t\t\t\tif (data.includes(\"'update-a', 'update-b'\")) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t9000,\n\t\t\t\t);\n\n\t\t\t\ttsxProcess.kill();\n\n\t\t\t\tconst tsxProcessResolved = await tsxProcess;\n\t\t\t\texpect(tsxProcessResolved.stderr).toBe('');\n\t\t\t}, 10_000);\n\t\t});\n\n\t\tdescribe('exclude (ignore)', ({ test }) => {\n\t\t\ttest('file path & glob', async ({ onTestFail }) => {\n\t\t\t\tconst entryFile = 'index.js';\n\t\t\t\tconst fileA = 'file-a.js';\n\t\t\t\tconst fileB = 'directory/file-b.js';\n\t\t\t\tconst depA = 'node_modules/a/index.js';\n\n\t\t\t\tawait using fixtureGlob = await createFixture({\n\t\t\t\t\t[fileA]: 'export default \"logA\"',\n\t\t\t\t\t[fileB]: 'export default \"logB\"',\n\t\t\t\t\t[depA]: 'export default \"logC\"',\n\t\t\t\t\t[entryFile]: `\n\t\t\t\t\t\timport valueA from './${fileA}'\n\t\t\t\t\t\timport valueB from './${fileB}'\n\t\t\t\t\t\timport valueC from './${depA}'\n\t\t\t\t\t\tconsole.log(valueA, valueB, valueC)\n\t\t\t\t\t`.trim(),\n\t\t\t\t});\n\n\t\t\t\tconst tsxProcess = tsx(\n\t\t\t\t\t[\n\t\t\t\t\t\t'watch',\n\t\t\t\t\t\t'--clear-screen=false',\n\t\t\t\t\t\t`--ignore=${fileA}`,\n\t\t\t\t\t\t'--exclude=directory/*',\n\t\t\t\t\t\tentryFile,\n\t\t\t\t\t],\n\t\t\t\t\tfixtureGlob.path,\n\t\t\t\t);\n\n\t\t\t\tonTestFail(async () => {\n\t\t\t\t\t// If timed out, force kill process\n\t\t\t\t\tif (tsxProcess.exitCode === null) {\n\t\t\t\t\t\tconsole.log('Force killing hanging process\\n\\n');\n\t\t\t\t\t\ttsxProcess.kill();\n\t\t\t\t\t\tconsole.log({\n\t\t\t\t\t\t\ttsxProcess: await tsxProcess,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tconst negativeSignal = 'fail';\n\n\t\t\t\tawait expect(\n\t\t\t\t\tprocessInteract(\n\t\t\t\t\t\ttsxProcess.stdout!,\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tasync (data) => {\n\t\t\t\t\t\t\t\tif (data !== 'logA logB logC\\n') {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// These changes should not trigger a re-run\n\t\t\t\t\t\t\t\tawait Promise.all([\n\t\t\t\t\t\t\t\t\tfixtureGlob.writeFile(fileA, `export default \"${negativeSignal}\"`),\n\t\t\t\t\t\t\t\t\tfixtureGlob.writeFile(fileB, `export default \"${negativeSignal}\"`),\n\t\t\t\t\t\t\t\t\tfixtureGlob.writeFile(depA, `export default \"${negativeSignal}\"`),\n\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t(data) => {\n\t\t\t\t\t\t\t\tif (data.includes(negativeSignal)) {\n\t\t\t\t\t\t\t\t\tthrow new Error('Unexpected re-run');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\t2000,\n\t\t\t\t\t),\n\t\t\t\t).rejects.toThrow('Timeout'); // Watch should not trigger\n\n\t\t\t\ttsxProcess.kill();\n\n\t\t\t\tawait tsxProcess;\n\t\t\t}, 10_000);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "tests/utils/coverage-sources-content.ts",
    "content": "import path from 'node:path';\nimport fs from 'node:fs/promises';\n\ntype SourceMapCache = Record<string, {\n\tdata: {\n\t\tsourcesContent: string[];\n\t} | null;\n}>;\n\nexport const hasCoverageSourcesContent = async (\n\tcoverageDirectory: string,\n) => {\n\tconst fileNames = await fs.readdir(coverageDirectory);\n\tconst coverageData = await Promise.all(\n\t\tfileNames.map(\n\t\t\tasync file => JSON.parse(\n\t\t\t\tawait fs.readFile(path.join(coverageDirectory, file), 'utf8'),\n\t\t\t),\n\t\t),\n\t);\n\treturn coverageData.some(coverage => (\n\t\tcoverage['source-map-cache']\n\t\t&& (\n\t\t\tObject.values(coverage['source-map-cache'] as SourceMapCache)\n\t\t\t\t.some(value => typeof value.data?.sourcesContent?.[0] === 'string')\n\t\t)\n\t));\n};\n"
  },
  {
    "path": "tests/utils/expect-match-in-order.ts",
    "content": "type Searchable = string | RegExp;\n\nconst stringify = (\n\tvalue: { toString(): string },\n) => JSON.stringify(\n\tvalue.toString(), // Might be RegExp which requires .toString()\n);\n\nconst expectedError = (\n\texpected: Searchable,\n\tbefore?: Searchable,\n) => new Error(`Expected ${stringify(expected)} ${before ? `to be after ${stringify(before)}` : ''}`);\n\nexport const expectMatchInOrder = (\n\tsubject: string,\n\texpectedOrder: Searchable[],\n) => {\n\tlet remaining = subject;\n\tfor (let i = 0; i < expectedOrder.length; i += 1) {\n\t\tconst previousElement = i > 0 ? expectedOrder[i - 1] : undefined;\n\t\tconst currentElement = expectedOrder[i];\n\n\t\tif (typeof currentElement === 'string') {\n\t\t\tconst index = remaining.indexOf(currentElement);\n\t\t\tif (index === -1) {\n\t\t\t\tthrow expectedError(currentElement, previousElement);\n\t\t\t}\n\t\t\tremaining = remaining.slice(index + currentElement.length);\n\t\t} else {\n\t\t\tconst match = remaining.match(currentElement);\n\t\t\tif (!match) {\n\t\t\t\tthrow expectedError(currentElement, previousElement);\n\t\t\t}\n\t\t\tremaining = remaining.slice(match.index! + match[0].length);\n\t\t}\n\t}\n};\n"
  },
  {
    "path": "tests/utils/get-node.ts",
    "content": "import _getNode from 'get-node';\n\nexport const getNode = async (\n\tnodeVersion: string,\n) => {\n\tif (nodeVersion === process.version) {\n\t\treturn {\n\t\t\tversion: process.versions.node,\n\t\t\tpath: process.execPath,\n\t\t};\n\t}\n\n\tconsole.log('Getting node', nodeVersion);\n\tconst startTime = Date.now();\n\tconst node = await _getNode(nodeVersion, {\n\t\tprogress: true,\n\t});\n\tconsole.log(`Got node in ${Date.now() - startTime}ms`, node);\n\n\treturn node;\n};\n"
  },
  {
    "path": "tests/utils/is-process-alive.ts",
    "content": "export const isProcessAlive = (pid: number) => {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch {}\n\treturn false;\n};\n"
  },
  {
    "path": "tests/utils/is-windows.ts",
    "content": "export const isWindows = process.platform === 'win32';\n"
  },
  {
    "path": "tests/utils/node-versions.ts",
    "content": "/**\n * The specific version is used in CI because of caching\n * Only pull the latest major version in development\n * and upgrade manually for CI when needed\n */\nconst latestMajor = (version: string) => (process.env.CI ? version : version.split('.')[0]);\n\nexport const nodeVersions = [\n\tprocess.version,\n\t...(\n\t\t(\n\t\t\tprocess.env.CI\n\t\t\t&& process.platform !== 'win32'\n\t\t)\n\t\t\t? [\n\t\t\t\tlatestMajor('22.6.0'),\n\t\t\t\tlatestMajor('21.7.3'),\n\t\t\t\tlatestMajor('20.17.0'),\n\t\t\t\tlatestMajor('18.20.3'),\n\t\t\t] as const\n\t\t\t: [] as const\n\t),\n] as const;\n"
  },
  {
    "path": "tests/utils/package-types.ts",
    "content": "export const packageTypes = [\n\tundefined,\n\t'module',\n\t'commonjs',\n] as const;\n"
  },
  {
    "path": "tests/utils/process-interact.ts",
    "content": "import type { Readable } from 'node:stream';\nimport { on } from 'node:events';\nimport { setTimeout } from 'node:timers/promises';\nimport stripAnsi from 'strip-ansi';\n\ntype OnTimeoutCallback = () => void;\n\ntype Api = {\n\tstartTime: number;\n\tonTimeout: (callback: OnTimeoutCallback) => void;\n};\n\nconst enforceTimeout = <ReturnType>(\n\ttimeout: number,\n\tfunction_: (api: Api) => ReturnType,\n): ReturnType => {\n\tconst startTime = Date.now();\n\tlet onTimeoutCallback: OnTimeoutCallback;\n\n\tconst runFunction = function_({\n\t\tstartTime,\n\t\tonTimeout: (callback) => {\n\t\t\tonTimeoutCallback = callback;\n\t\t},\n\t});\n\n\tif (!(runFunction instanceof Promise)) {\n\t\treturn runFunction;\n\t}\n\n\tconst ac = new AbortController();\n\tconst timer = setTimeout(timeout, true, ac).then(\n\t\tasync () => {\n\t\t\tif (onTimeoutCallback) {\n\t\t\t\tawait onTimeoutCallback();\n\t\t\t}\n\n\t\t\tthrow new Error('Timeout');\n\t\t},\n\t\t() => { /* Timeout aborted */ },\n\t);\n\n\treturn Promise.race([\n\t\trunFunction.finally(() => ac.abort()),\n\t\ttimer,\n\t]) as ReturnType;\n};\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport const processInteract = async (\n\tstdout: Readable,\n\tactions: ((data: string) => MaybePromise<boolean | void>)[],\n\ttimeout: number,\n) => enforceTimeout(timeout, async ({ startTime, onTimeout }) => {\n\tconst logs: {\n\t\ttime: number;\n\t\tstdout: string;\n\t}[] = [];\n\n\tlet currentAction = actions.shift();\n\n\tonTimeout(() => {\n\t\tif (currentAction) {\n\t\t\tconst error = Object.assign(\n\t\t\t\tnew Error(`Timeout ${timeout}ms exceeded:`),\n\t\t\t\t{ logs },\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t});\n\n\twhile (currentAction) {\n\t\tfor await (const [chunk] of on(stdout, 'data')) {\n\t\t\tconst chunkString = stripAnsi(chunk.toString());\n\t\t\tlogs.push({\n\t\t\t\ttime: Date.now() - startTime,\n\t\t\t\tstdout: chunkString,\n\t\t\t});\n\n\t\t\tconst gotoNextAction = await currentAction(chunkString);\n\t\t\tif (gotoNextAction) {\n\t\t\t\tcurrentAction = actions.shift();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "tests/utils/pty-shell/index.ts",
    "content": "import { spawn, waitFor } from 'pty-spawn';\nimport stripAnsi from 'strip-ansi';\n\nexport const isWindows = process.platform === 'win32';\nconst shell = isWindows ? 'powershell.exe' : 'bash';\nconst commandCaret = `${isWindows ? '>' : '$'} `;\n\nexport const ptyShell = () => {\n\tconst subprocess = spawn(shell, {\n\t\twindow: { cols: 1000 },\n\t\treject: false,\n\t});\n\n\treturn {\n\t\twaitForPrompt: () => waitFor(subprocess, o => o.endsWith(commandCaret)),\n\t\twaitForLine: (pattern: RegExp) => waitFor(subprocess, o => (\n\t\t\tstripAnsi(o).split('\\n').some(line => pattern.test(line.replace(/\\r$/, '')))\n\t\t)),\n\t\ttype: (text: string) => subprocess.stdin.write(`${text}\\r`),\n\t\tpress: (key: string) => subprocess.stdin.write(key),\n\t\tclose: async () => {\n\t\t\tawait subprocess.kill();\n\t\t\tconst result = await subprocess;\n\t\t\treturn stripAnsi(result.output);\n\t\t},\n\t\tgetOutput: () => subprocess.output,\n\t};\n};\n"
  },
  {
    "path": "tests/utils/tsx.ts",
    "content": "import { fileURLToPath } from 'node:url';\nimport { execaNode, type NodeOptions } from 'execa';\nimport {\n\tisFeatureSupported,\n\tmoduleRegister,\n\ttestRunnerGlob,\n\tesmLoadReadFile,\n\trequireEsm,\n\ttype Version,\n} from '../../src/utils/node-features.js';\nimport { getNode } from './get-node.js';\n\ntype Options = {\n\targs: string[];\n\tnodePath?: string;\n\tcwd?: string;\n};\n\nexport const tsxPath = fileURLToPath(new URL('../../dist/cli.mjs', import.meta.url).toString());\nexport const tsxCjsPath = fileURLToPath(new URL('../../dist/cjs/index.cjs', import.meta.url).toString());\nexport const tsxCjsApiPath = fileURLToPath(new URL('../../dist/cjs/api/index.cjs', import.meta.url).toString());\nexport const tsxEsmPath = new URL('../../dist/esm/index.mjs', import.meta.url).toString();\nexport const tsxEsmApiPath = new URL('../../dist/esm/api/index.mjs', import.meta.url).toString();\nexport const tsxEsmApiCjsPath = fileURLToPath(new URL('../../dist/esm/api/index.cjs', import.meta.url).toString());\n\nconst cjsPatchPath = fileURLToPath(new URL('../../dist/cjs/index.cjs', import.meta.url).toString());\nconst hookPath = new URL('../../dist/esm/index.cjs', import.meta.url).toString();\n\nexport const tsx = (\n\toptions: Options,\n) => execaNode(\n\ttsxPath,\n\toptions.args,\n\t{\n\t\tenv: {\n\t\t\tTSX_DISABLE_CACHE: '1',\n\t\t\tDEBUG: '1',\n\t\t},\n\t\tnodePath: options.nodePath,\n\t\tnodeOptions: [],\n\t\tcwd: options.cwd,\n\t\treject: false,\n\t\tall: true,\n\t},\n);\n\nexport const createNode = async (\n\tnodeVersion: string,\n) => {\n\tconst node = await getNode(nodeVersion);\n\tconst versionParsed = node.version.split('.').map(Number) as Version;\n\tconst supports = {\n\t\tmoduleRegister: isFeatureSupported(moduleRegister, versionParsed),\n\n\t\ttestRunnerGlob: isFeatureSupported(testRunnerGlob, versionParsed),\n\n\t\t// https://nodejs.org/docs/latest-v18.x/api/cli.html#--test\n\t\tcliTestFlag: isFeatureSupported([[18, 1, 0]], versionParsed),\n\n\t\tcjsInterop: isFeatureSupported(esmLoadReadFile, versionParsed),\n\n\t\trequireEsm: isFeatureSupported(requireEsm, versionParsed),\n\t};\n\tconst hookFlag = supports.moduleRegister ? '--import' : '--loader';\n\n\treturn {\n\t\tversion: node.version,\n\n\t\tpath: node.path,\n\n\t\tsupports,\n\n\t\ttsx: (\n\t\t\targs: string[],\n\t\t\tcwdOrOptions?: string | NodeOptions,\n\t\t) => {\n\t\t\tconst isCwd = typeof cwdOrOptions === 'string';\n\t\t\treturn execaNode(\n\t\t\t\ttsxPath,\n\t\t\t\targs,\n\t\t\t\t{\n\t\t\t\t\tnodePath: node.path,\n\t\t\t\t\tnodeOptions: [],\n\t\t\t\t\treject: false,\n\t\t\t\t\tall: true,\n\t\t\t\t\t...(\n\t\t\t\t\t\tisCwd\n\t\t\t\t\t\t\t? { cwd: cwdOrOptions }\n\t\t\t\t\t\t\t: cwdOrOptions\n\t\t\t\t\t),\n\t\t\t\t\tenv: {\n\t\t\t\t\t\tTSX_DISABLE_CACHE: '1',\n\t\t\t\t\t\tDEBUG: '1',\n\t\t\t\t\t\t...(\n\t\t\t\t\t\t\t(cwdOrOptions && !isCwd)\n\t\t\t\t\t\t\t\t? cwdOrOptions.env\n\t\t\t\t\t\t\t\t: {}\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\n\t\tcjsPatched: (\n\t\t\targs: string[],\n\t\t\tcwd?: string,\n\t\t) => execaNode(args[0], args.slice(1), {\n\t\t\tcwd,\n\t\t\tnodePath: node.path,\n\t\t\tnodeOptions: ['--require', cjsPatchPath],\n\t\t}),\n\n\t\thook: (\n\t\t\targs: string[],\n\t\t\tcwd?: string,\n\t\t) => execaNode(args[0], args.slice(1), {\n\t\t\tcwd,\n\t\t\tnodePath: node.path,\n\t\t\tnodeOptions: [hookFlag, hookPath],\n\t\t}),\n\t};\n};\n\nexport type NodeApis = Awaited<ReturnType<typeof createNode>>;\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"es2022\",\n\t\t\"moduleDetection\": \"force\",\n\n\n\t\t\"module\": \"preserve\",\n\t\t\"resolveJsonModule\": true,\n\t\t\"allowJs\": true,\n\t\t\"strict\": true,\n\t\t// \"noUncheckedIndexedAccess\": true,\n\t\t\"noImplicitOverride\": true,\n\t\t\"noEmit\": true,\n\t\t\"esModuleInterop\": true,\n\t\t\"verbatimModuleSyntax\": true,\n\t\t\"skipLibCheck\": true,\n\t}\n}\n"
  }
]