lukeed / tsm

TypeScript Module Loader
MIT License
1.18k stars 19 forks source link

New loader hooks api #13

Closed TrySound closed 2 years ago

TrySound commented 2 years ago

Node 16 just landed new loader hooks api. Is tsm compatible with it? https://github.com/nodejs/node/releases/tag/v16.12.0

lukeed commented 2 years ago

I assume not since it was released 1 hour ago and has been raised in the "Notable Changes" section 😄

TrySound commented 2 years ago

Node 17 got it first yesterday 😄

lukeed commented 2 years ago

I'll take a look later today or tomorrow. Specifically I'm interested in if this is backwards compatible at all (notes mention deprecation warning for old hooks, but does that mean feature loss?) and if this is likely the final design. I know it's experimental, but reworking tsm every release will make tsm versioning difficult

karlhorky commented 2 years ago

Yeah, it breaks (saw this first on CI, because GitHub Actions with node-version: '16' upgraded to 16.12.0 silently):

$ tsm index.ts
(node:3063) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /home/runner/work/project/index.ts
    at new NodeError (node:internal/errors:371:5)
    at Object.file: (node:internal/modules/esm/get_format:72:15)
    at defaultGetFormat (node:internal/modules/esm/get_format:85:38)
    at defaultLoad (node:internal/modules/esm/load:13:42)
    at ESMLoader.load (node:internal/modules/esm/loader:303:26)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:230:58)
    at new ModuleJob (node:internal/modules/esm/module_job:63:26)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:244:11)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:281:24) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
karlhorky commented 2 years ago

Apparently this is the PR with the new hooks implementation in ts-node: https://github.com/TypeStrong/ts-node/pull/1457

lukeed commented 2 years ago

Thanks but the implementation isn't the obstacle. It was supporting both loader APIs without inducing a breaking change. It dawned on me how to do it last night so will implement shortly.

This way, the majority of users with older 16 versions can continue using it, and CI/bleeding edge installs can use the new one.

This feels like the best (and necessary) approach since there's no 16 LTS yet for me to point to as a firm requirement.

PabloSzx commented 2 years ago

Thanks but the implementation isn't the obstacle. It was supporting both loader APIs without inducing a breaking change. It dawned on me how to do it last night so will implement shortly.

This way, the majority of users with older 16 versions can continue using it, and CI/bleeding edge installs can use the new one.

This feels like the best (and necessary) approach since there's no 16 LTS yet for me to point to as a firm requirement.

I adapted it using semver to detect the Node.js version and doing:

HAS_UPDATED_HOOKS
  ? undefined
  : async function (...

Check https://github.com/PabloSzx/bob-esbuild/blob/main/packages/bob-tsm/src/loader.ts for that and how the load hook works, bob-tsm works perfectly in both <16.12.0 and >=16.12.0

PS: btw, I created bob-tsm using tsm as inspiration but adding opinionated changes, like watch mode, esbuild as peer dependency, and extra cli options

lukeed commented 2 years ago

Yes that's what it will be.

Thanks but PS I should be mentioned in the license for that package.

karlhorky commented 2 years ago

Thanks @lukeed ! 🙌

TrySound commented 2 years ago

Thanks, very cool!