Fix broken "types" entries across the three build-info packages - #565
Merged
Merged
Conversation
"types" was "build/index.d.ts", a file this package never produces and never shipped — tsdown emits "build/build-info.d.mts" from the "build-info.ts" entry. The published 0.0.1 tarball contains only build-info.mjs and build-info.d.mts, so consumers got no types at all and had to "declare module" locally. The stale path was copied from the two plugin packages, where build/index.d.ts is a hand-written, git-tracked type entry (which is also why they set "clean": false). This package has no such file, so point "types" at the emitted declaration instead. Also annotate the exported constants explicitly. The published build-info.d.mts declares "branch" and "commit" as "any" because the dts pass resolved without node types; annotating makes the emitted types deterministic regardless of the publish environment. Verified by packing the tarball and typechecking a consumer that imports branch/commit/timestamp under moduleResolution: nodenext, with no declare-module shim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VLKGKWWvgHcF8JR64yZj6P
Both plugins ship a hand-written build/index.d.ts as their "types" entry,
and both fail to typecheck in a consumer under either moduleResolution:
"bundler" or "nodenext".
esbuild-plugin-build-info:
export { BuildInfo } from "./build-info";
build-info.d.ts is the ambient declaration for the virtual "build-info"
module — a global script, not a module — so this errors with TS2306
("not a module") under bundler and TS2834 (needs a file extension) under
nodenext. Because the file was imported rather than referenced, its
"declare module" never entered the program either, so consumers importing
the injected virtual module got TS2307 "Cannot find module 'build-info'".
The declarations were also missing branch, commit and buildInfo, which
the plugin has always exported at runtime.
Replaced with a /// <reference path> plus the full export surface,
mirroring esbuild-plugin-build-info.ts and matching what the rollup
plugin already exposes.
rollup-plugin-build-info:
export { ... } from "./rollup-plugin-build-info.d.mts";
Importing a declaration file directly is TS2846; the specifier has to
name the implementation, so point it at ./rollup-plugin-build-info.mjs
and let TypeScript find the sibling .d.mts.
Also widen the esbuild peer range from "^0.20.0" to ">=0.20.0". esbuild
is 0.x, so a caret pins the minor: "^0.20.0" excludes everything from
0.21 up, including the 0.28.2 this package develops against. Installing
it alongside a current esbuild fails ERESOLVE on npm.
Verified by packing both tarballs and typechecking consumers that import
the default export, every named export, and the injected virtual module,
under both bundler and nodenext resolution — all four combinations pass,
and the install now resolves without --legacy-peer-deps.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLKGKWWvgHcF8JR64yZj6P
iainmerrick
approved these changes
Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
All three build-info packages ship a
"types"entry that fails for consumers. Each one is broken differently; none of them can be fixed by republishing alone.Verified empirically throughout: packing each tarball, installing it into a scratch project, and typechecking real imports under both
moduleResolution: "bundler"and"nodenext".1.
@moreplease/build-info—"types"points at a file that doesn't exist"types"wasbuild/index.d.ts, but tsdown builds thebuild-info.tsentry intobuild/build-info.mjs+build/build-info.d.mts. The published 0.0.1 tarball contains exactly:So consumers get no types and have to work around it:
The stale path looks copied from the two plugin packages, where
build/index.d.tsis a hand-written, git-tracked type entry (which is also why they set"clean": false). This package has no such file.Fixed:
"types"→build/build-info.d.mts, pairing with the already-correct"main".Also annotated the exported constants explicitly. The published
build-info.d.mtsdeclaresbranchandcommitasanybecause the dts pass resolved without node types; annotating makes the emitted declarations deterministic regardless of publish environment, and matches what the workaround above assumed (string).2.
@moreplease/esbuild-plugin-build-info— declarations don't compile, and are incompletebuild-info.d.tsis the ambient declaration for the virtual"build-info"module — a global script, not a module. So this errors for every consumer: TS2306 (not a module) under bundler, TS2834 (needs a file extension) under nodenext.Because that file was imported rather than referenced, its
declare modulenever entered the program either. Consumers importing the module the plugin injects got:The declarations were also missing
branch,commitandbuildInfo, which the plugin has always exported at runtime — importing any of them was a TS2724/TS2614 error.Fixed: replaced with a triple-slash reference directive plus the full export surface, mirroring
esbuild-plugin-build-info.tsand matching what the rollup plugin already exposes:Bonus: the esbuild peer range excludes every current esbuild
esbuild is 0.x, so a caret pins the minor —
^0.20.0means>=0.20.0 <0.21.0. That excludes everything from 0.21 up, including the^0.28.2this package develops against. Installing the plugin next to a current esbuild fails outright:Fixed: widened to
>=0.20.0. The install now resolves without--legacy-peer-deps.3.
@moreplease/rollup-plugin-build-info— declaration entry imports a declaration fileImporting a
.d.mtsdirectly is TS2846 (A declaration file cannot be imported without 'import type'), under both resolution modes. The specifier has to name the implementation.Fixed: point it at
./rollup-plugin-build-info.mjsand let TypeScript find the sibling.d.mts.Verification
Consumer typecheck matrix, against packed tarballs — default export, every named export, and the injected virtual module:
All four plugin combinations failed before this change.
pnpm test(tsc) passes in all three packages.Worth noting the pattern behind all three bugs:
pnpm testistscover each package's own sources, so it never typechecks thebuild/*.d.tsfiles consumers actually receive. A small smoke-test consumer package in CI would have caught every one of these. Happy to add one as a follow-up if that seems worthwhile.Versions
Bumped
build-info0.0.1 → 0.0.2,esbuild-plugin-build-info0.0.3 → 0.0.4,rollup-plugin-build-info0.0.13 → 0.0.14, since these fixes only reach consumers via a republish.Notes, not addressed here
build-infoREADME documents a default export and aBuildInfotype (import buildInfo from "build-info"), which the plugins' virtual modules provide but the runtime placeholder does not — it only has the three named exports. That's a public-API change rather than a packaging fix.rollup-plugin-build-info/build/rollup-plugin-build-info.{mjs,d.mts}are git-tracked even though.gitignorelistsbuildand tsdown regenerates them onprepare. Only the two hand-written.d.tsfiles need tracking. I checked and they're not currently stale, so this is cosmetic — left alone to keep the diff focused.