privatenumber / tsx

⚡️ TypeScript Execute | The easiest way to run TypeScript in Node.js
https://tsx.is
MIT License
9.42k stars 144 forks source link

tsx should come first when chaining loaders #571

Open timfish opened 3 months ago

timfish commented 3 months ago

Acknowledgements

Minimal reproduction URL

Below

Problem & expected behavior (under 200 words)

There were previous issues with import-in-the-middle which are now fixed. The issue now is that import-in-the-middle cannot parse TypeScript and there's no way to get the loaders in the correct order

  "dependencies": {
    "import-in-the-middle": "1.8.0",
    "tsx": "4.11.2",
    "typescript": "5.4.5"
  },

test.ts

import { test } from './another'
console.assert(test)

another.ts

export function test(input: string) {
  return input
}
tsx --loader import-in-the-middle/hook.mjs ./test.ts

Results in an error because import-in-the-middle cannot parse TypeScript:

SyntaxError [Error]: Unexpected token (1:26)
    at pp$4.raise (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:3573:15)
    at pp$9.unexpected (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:772:10)
    at pp$9.expect (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:766:28)
    at pp$7.parseBindingList (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:2077:19)
    at pp$8.parseFunctionParams (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:1386:24)
    at pp$8.parseFunction (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:1375:10)
    at pp$8.parseFunctionStatement (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:1070:17)
    at pp$8.parseStatement (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:915:19)
    at Parser.parseExport (/Users/tim/Documents/Repositories/repro/node_modules/acorn-import-attributes/lib/index.js:184:33)
    at pp$8.parseStatement (/Users/tim/Documents/Repositories/repro/node_modules/acorn/dist/acorn.js:948:76) {
  pos: 26,
  loc: { line: 1, column: 26 },
  raisedAt: 27
}

Looking at the stack before this occurs we can see that the loaders are ordered as follows, which means that the tsx loader is trying to fetch TypeScript code through the iitm loader:

tsx > iitm > default

Error
    at getExports (/Users/tim/Documents/Repositories/import-in-the-middle/lib/get-exports.js:77:21)
    at async processModule (/Users/tim/Documents/Repositories/import-in-the-middle/hook.js:131:23)
    at async getSource (/Users/tim/Documents/Repositories/import-in-the-middle/hook.js:249:23)
    at async load (/Users/tim/Documents/Repositories/import-in-the-middle/hook.js:280:26)
    at async nextLoad (node:internal/modules/esm/hooks:833:22)
    at async z (file:///Users/tim/Documents/Repositories/import-in-the-middle/node_modules/tsx/dist/esm/index.mjs?1717578797987=:2:1643)
    at async nextLoad (node:internal/modules/esm/hooks:833:22)
    at async Hooks.load (node:internal/modules/esm/hooks:416:20)
    at async handleMessage (node:internal/modules/esm/worker:168:18) {

This is because of the following code which means that --import and --loader args are always registered after tsx own loader: https://github.com/privatenumber/tsx/blob/aa2b639a9bac8ae28a46b847013fda7f5cd4466b/src/run.ts#L36-L46

Bugs are expected to be fixed by those affected by it

Compensating engineering work financially will speed up resolution

gajus commented 3 months ago

@privatenumber This would also solve the fundamental problem that I flagged in the other thread – about making open-telemetry work with tsx.

timfish commented 3 months ago

I guess if the order was swapped it would mean that --import files could not be TypeScript because the loader wouldn't be registered yet.

I suspect the one solution might be to put the TypeScript imports after the tsx loaders and everything else before? Or maybe add another option --import-first which get added first?

artsiommiksiuk commented 2 weeks ago

I can +1 on this one. I need my loaders to come last, and can't make it because tsx imports via subprocessing.