diff --git a/src/client.ts b/src/client.ts index 05fce0e..f1d6407 100644 --- a/src/client.ts +++ b/src/client.ts @@ -87,15 +87,19 @@ export class DaemonClient extends SockDaemonClient< } /** - * Translate a file like ./src/foo.js into ./src/foo.ts + * Translate a module identifier like ./src/foo.js into + * file:///path/to/src/foo.ts * A file that isn't .ts or isn't a file:// url is returned as-is. */ async resolve(url: string, parentURL?: string): Promise { - const { fileName } = (await this.request({ - action: 'resolve', - url, - parentURL, - })) as ResolveResult - return fileName ?? url + return ( + ( + (await this.request({ + action: 'resolve', + url, + parentURL, + })) as ResolveResult + )?.url ?? url + ) } } diff --git a/src/hooks/hooks.mts b/src/hooks/hooks.mts index 7441cb1..6f33843 100644 --- a/src/hooks/hooks.mts +++ b/src/hooks/hooks.mts @@ -62,20 +62,30 @@ export const resolve: ResolveHook = async ( String(new URL(url, parentURL)) : url return nextResolve( - target.startsWith('file://') && !target.startsWith(nm) + target.startsWith('file://') && !startsWithCS(target, nm) ? await getClient().resolve(url, parentURL) : url, context ) } +// case (in-)sensitive String.startsWith +const cs = + process.platform !== 'win32' && process.platform !== 'darwin' +/* c8 ignore start */ +const startsWithCS = cs + ? (haystack: string, needle: string) => haystack.startsWith(needle) + : (haystack: string, needle: string) => + haystack.toUpperCase().startsWith(needle.toUpperCase()) +/* c8 ignore stop */ + // ts programs have import filenames like ./x.js, but the source // lives in ./x.ts. Find the source and compile it. const nm = String(pathToFileURL(pathResolve('node_modules'))) + '/' const proj = String(pathToFileURL(process.cwd())) + '/' let hookedCJS = false export const load: LoadHook = async (url, context, nextLoad) => { - if (url.startsWith(proj) && !url.startsWith(nm)) { + if (startsWithCS(url, proj) && !startsWithCS(url, nm)) { const inputFile = fileURLToPath(url) const { fileName, diagnostics } = await getClient().compile( inputFile, diff --git a/src/service/service.ts b/src/service/service.ts index 1d5c860..9d5c074 100644 --- a/src/service/service.ts +++ b/src/service/service.ts @@ -81,13 +81,14 @@ export class DaemonServer extends SockDaemonServer< url.startsWith('./') || url.startsWith('../') ? String(new URL(url, parentURL)) : url - if (target.startsWith('file://')) { - const tsFile = findTsFile(target) + const tsFile = findTsFile(target) + if (tsFile) { + const url = new URL(target) + url.pathname = pathToFileURL(tsFile).pathname + if (tsFile) { - const queryIndex = target.indexOf('?') - const query = queryIndex >= 0 ? target.slice(queryIndex) : '' return { - fileName: String(pathToFileURL(tsFile)) + query, + url: String(url), } } } diff --git a/src/types.ts b/src/types.ts index a706ed8..29bd752 100644 --- a/src/types.ts +++ b/src/types.ts @@ -43,7 +43,7 @@ export type ServiceResolveRequest = MessageBase & } export type ResolveResult = { - fileName?: string + url?: string } export type ServiceResolveResult = MessageBase & ResolveResult & { diff --git a/test/client.ts b/test/client.ts index 694a75f..eacfc78 100644 --- a/test/client.ts +++ b/test/client.ts @@ -32,12 +32,15 @@ t.strictSame(await client.preload(), {}) t.strictSame(requests, [{ action: 'preload' }]) requests.length = 0 -MockSDC.response = { fileName: 'some-file.js' } -t.strictSame(await client.resolve('file:///x/y/z.ts'), 'some-file.js') +MockSDC.response = { url: 'file:///x/y/z/some-file.ts' } +t.strictSame( + await client.resolve('file:///x/y/z.js'), + 'file:///x/y/z/some-file.ts' +) t.strictSame(requests, [ { action: 'resolve', - url: 'file:///x/y/z.ts', + url: 'file:///x/y/z.js', parentURL: undefined, }, ]) diff --git a/test/service/service.ts b/test/service/service.ts index 5aebadc..042d687 100644 --- a/test/service/service.ts +++ b/test/service/service.ts @@ -45,7 +45,7 @@ t.test('resolve', async t => { url: String(pathToFileURL(resolve(dir, 'foo.ts'))), }), { - fileName: String(pathToFileURL(resolve(dir, 'foo.ts'))), + url: String(pathToFileURL(resolve(dir, 'foo.ts'))), } ) t.strictSame( @@ -55,7 +55,7 @@ t.test('resolve', async t => { url: String(pathToFileURL(resolve(dir, 'foo.js'))), }), { - fileName: String(pathToFileURL(resolve(dir, 'foo.ts'))), + url: String(pathToFileURL(resolve(dir, 'foo.ts'))), } ) t.strictSame( @@ -65,7 +65,7 @@ t.test('resolve', async t => { url: String(pathToFileURL(resolve(dir, 'bar.js'))), }), { - fileName: String(pathToFileURL(resolve(dir, 'bar.tsx'))), + url: String(pathToFileURL(resolve(dir, 'bar.tsx'))), } ) @@ -77,7 +77,7 @@ t.test('resolve', async t => { parentURL: String(pathToFileURL(resolve(dir, 'bar.ts'))), }), { - fileName: String(pathToFileURL(resolve(dir, 'foo.ts'))), + url: String(pathToFileURL(resolve(dir, 'foo.ts'))), } ) t.strictSame( @@ -88,7 +88,7 @@ t.test('resolve', async t => { parentURL: String(pathToFileURL(resolve(dir, 'bar.js'))), }), { - fileName: String(pathToFileURL(resolve(dir, 'foo.ts'))), + url: String(pathToFileURL(resolve(dir, 'foo.ts'))), } ) t.strictSame( @@ -99,7 +99,7 @@ t.test('resolve', async t => { parentURL: String(pathToFileURL(resolve(dir, 'foo.js'))), }), { - fileName: String(pathToFileURL(resolve(dir, 'bar.tsx'))), + url: String(pathToFileURL(resolve(dir, 'bar.tsx'))), } ) @@ -127,7 +127,7 @@ t.test('resolve', async t => { String(pathToFileURL(resolve(dir, 'foo.ts'))) + '?name=value', }), { - fileName: + url: String(pathToFileURL(resolve(dir, 'foo.ts'))) + '?name=value', } ) @@ -139,7 +139,7 @@ t.test('resolve', async t => { String(pathToFileURL(resolve(dir, 'foo.js'))) + '?name=value', }), { - fileName: + url: String(pathToFileURL(resolve(dir, 'foo.ts'))) + '?name=value', } )