-
Notifications
You must be signed in to change notification settings - Fork 17
feat(types): migrate core modules to TypeScript (Phase 5.4) #554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
3b8e612
2c3d27b
4bfc950
26cc36c
37ac14f
2ab13ab
447510a
bb22706
8ae7c6d
d1dc03b
65dcb2a
897993b
306b833
7465f9b
b08ce30
4a63243
d0b4b8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /** | ||
| * ESM resolve/load hooks for .js → .ts fallback during gradual migration. | ||
| * | ||
| * - resolve: when a .js specifier resolves to a path that doesn't exist, | ||
| * check if a .ts version exists and redirect to it. | ||
| * - load: for .ts files, strip type annotations using Node 22's built-in | ||
| * --experimental-strip-types via a source transform. | ||
| */ | ||
|
|
||
| import { existsSync } from 'node:fs'; | ||
| import { readFile } from 'node:fs/promises'; | ||
| import { fileURLToPath, pathToFileURL } from 'node:url'; | ||
|
|
||
| export async function resolve(specifier, context, nextResolve) { | ||
| try { | ||
| return await nextResolve(specifier, context); | ||
| } catch (err) { | ||
| // Only intercept ERR_MODULE_NOT_FOUND for .js specifiers | ||
| if (err.code === 'ERR_MODULE_NOT_FOUND' && specifier.endsWith('.js')) { | ||
| const tsSpecifier = specifier.replace(/\.js$/, '.ts'); | ||
| try { | ||
| return await nextResolve(tsSpecifier, context); | ||
| } catch { | ||
| // .ts also not found — throw the original error | ||
| } | ||
| } | ||
| throw err; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| /** | ||
| * Node.js ESM loader hook for the JS → TS gradual migration. | ||
| * | ||
| * When a .js import specifier can't be found on disk, this loader tries the | ||
| * corresponding .ts file. This lets plain .js files import from already- | ||
| * migrated .ts modules without changing their import specifiers. | ||
| * | ||
|
Comment on lines
+1
to
+7
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The Consider adding a version guard before registering the hooks: import { createRequire } from 'node:module';
const _req = createRequire(import.meta.url);
// module.register() was added in Node 20.6.0
const [major, minor] = process.versions.node.split('.').map(Number);
if (major > 20 || (major === 20 && minor >= 6)) {
const { register } = await import('node:module');
const hooksURL = new URL('./ts-resolve-hooks.js', import.meta.url);
register(hooksURL.href, { parentURL: import.meta.url });
}Or update the minimum Node constraint in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed — |
||
| * Usage: node --import ./scripts/ts-resolve-loader.js ... | ||
| * (or via NODE_OPTIONS / vitest poolOptions.execArgv) | ||
| */ | ||
|
|
||
| import { register } from 'node:module'; | ||
|
|
||
| const hooksURL = new URL('./ts-resolve-hooks.js', import.meta.url); | ||
| register(hooksURL.href, { parentURL: import.meta.url }); | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
loadhookThe module header documents a
loadhook for.tsfiles ("strip type annotations using Node 22's built-in--experimental-strip-types"), but only theresolvehook was implemented. As a result, all three imports on these lines are completely unused:existsSyncfromnode:fs— never calledreadFilefromnode:fs/promises— never calledfileURLToPath/pathToFileURLfromnode:url— never calledThe actual TypeScript stripping is delegated to the global
--experimental-strip-typesNode flag set invitest.config.js, so theloadhook may not be needed at all. Either remove the dead imports or implement the intendedloadhook.Or remove all three import lines if no
loadhook is planned.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — removed all unused imports (
existsSync,readFile,fileURLToPath,pathToFileURL). Added the missingloadhook that handles.tsfiles: triesnextLoadfirst (works on Node >= 22.6 with--experimental-strip-types), falls back to reading the file as module source.