fix(emitDts): drop declarations emitted outside declarationDir#2965
fix(emitDts): drop declarations emitted outside declarationDir#2965joeinnes wants to merge 3 commits intosveltejs:masterfrom
Conversation
…arationDir Adds a sample where a Svelte component imports a TypeScript module from outside libRoot, triggering TypeScript to emit declarations outside the configured declarationDir. Also extends the test runner to detect and clean up any .d.ts files written outside declarationDir, asserting that none are produced.
When a Svelte component imports TypeScript files from outside the configured libRoot, TypeScript follows those imports and tries to emit declarations for them. Because those files are outside the forced rootDir, TypeScript falls back to emitting declarations using their absolute path as the output location rather than placing them inside declarationDir. Two related issues are fixed in the writeFile hook: 1. Only prepend pathPrefix when fileName is not already absolute. The previous unconditional path.join caused the absolute output path to be appended to pathPrefix, doubling the path and writing files deep inside the source tree. 2. Silently drop any .d.ts or .d.ts.map write whose resolved destination falls outside declarationDir. This prevents declarations for out-of-rootDir imports from polluting the source directory. Resolves: declarations written outside declarationDir when source files are imported from outside libRoot.
|
|
Can you provide a reproduction repository? I don't quite understand the problem you're trying to fix. |
Demonstrates sveltejs/language-tools#2182, fixed by sveltejs/language-tools#2965. Library maintainers using svelte-package with Svelte components that import TypeScript from outside libRoot find stray .d.ts files written into their source tree. Includes the cleanup workaround script that projects like jazz-tools are currently forced to maintain.
|
Sure, so for context, I'm a maintainer over at garden-co/jazz, where we're building a database product with a bunch of different capabilities. We offer Svelte bindings to allow users to build their Jazz apps with Svelte. We're running into an annoying issue where we need to run a clean-up step every time we build our repo, because the This repro should demo it: https://github.com/joeinnes/emitdts-repro Clone, install deps, and run the build script ( |
Fixes #2182
Problem
When a Svelte component imports a TypeScript module from outside the configured
libRoot, TypeScript follows the import and attempts to emit a declaration file for that module. BecauseemitDtsforcesrootDir: config.libRoot, the imported file is outsiderootDir, and TypeScript falls back to emitting its declaration using the file's absolute path as the output location — rather than placing it insidedeclarationDir. This pollutes the source tree with unwanted.d.tsfiles.A second related bug compounds this: the
writeFilehook unconditionally prependedpathPrefix(a relative path) to TypeScript's output filename usingpath.join. When TypeScript generated an absolute output path for the out-of-rootDirfile,path.joinappended the relative prefix to it, doubling the path and writing files deep inside a fake directory tree within the source tree (as reported in #2182).Reproduce
A project where:
libRoot(or-i) points to a subdirectory (e.g.src/).tsfile from outside it (e.g.../utils/helper.ts)emitDts(orsvelte-package) is runResult: a declaration file for the imported module appears outside
declarationDir, either next to the source or at a doubled absolute path inside the source tree.Fix
Two changes to the
writeFilehook increateTsCompilerHost:Guard
pathPrefixwith!path.isAbsolute(fileName)— only prepend the relative prefix when TypeScript has produced a relative output path. Fixes the doubled-path write (Emit dts not respecting abs path #2182).Drop
.d.ts/.d.ts.mapwrites outsidedeclarationDir— after resolving the final output path, silently skip any declaration file whose destination is not withindeclarationDir. This prevents out-of-rootDirimports from emitting declarations into the source tree.Tests
Added a new
emitDtssample (typescript-imports-outside-lib-root) where a Svelte component imports from outsidelibRoot. The test runner was extended to assert that no.d.tsfiles appear outsidedeclarationDirafteremitDtscompletes, and to clean up any such files (including newly-created directory trees) if the assertion fails.