Reproduction link or steps
This description is generated using codex. I thought I created an issue but I cannot find it so this may be a duplicate.
I am trying to use tsdown with unbundle: true for a package that has an aggregate entry file and separate public subpath/facade entry files.
The simplified setup looks like this:
packages/
ui/
index.js
card/
index.js
components/
card.js
content-card.js
The aggregate entry is packages/ui/index.js:
The card package has its own public facade file at packages/card/index.js:
export { default as Card } from './components/card.js';
export { BigCard } from './components/content-card.js';
The package export map points ./card at the generated facade path:
{
"exports": {
".": "./dist/packages/ui/index.mjs",
"./card": "./dist/packages/card/index.mjs"
}
}
I have attached a sample project
tsdown-unbundle-facade-repro.zip
What is expected?
With unbundle: true, I expected tsdown to transform the reachable module graph while preserving file-level public entry/facade modules. In this case, I expected the build output to include:
dist/packages/ui/index.mjs
dist/packages/card/index.mjs
dist/packages/card/components/card.mjs
dist/packages/card/components/content-card.mjs
The important file is dist/packages/card/index.mjs. I expected it to preserve the public facade exports
What is actually happening?
Instead, tsdown emits the aggregate root and the implementation files, but does not emit the transitive facade module:
dist/packages/ui/index.mjs
dist/packages/card/components/card.mjs
dist/packages/card/components/content-card.mjs
The generated root file directly imports the implementation modules:
import Card from "../card/components/card.mjs";
import { BigCard } from "../card/components/content-card.mjs";
export { BigCard, Card };
So the root package import works but the subpath export is broken because dist/packages/card/index.mjs does not exist:
import { Card } from 'tsdown-unbundle-facade-repro/card';
Any additional comments?
This is surprising because packages/card/index.js is directly reachable from the aggregate entry and is also a public package facade/subpath target. Since unbundle mode is described as focusing on code transformation without combining files, I expected the reachable facade module to remain present in the output rather than being bypassed.
The workaround is to add packages/card/index.js as an explicit entry, but that does not scale well for a package that has many public facade/subpath modules reachable from a single aggregate entry.
Reproduction link or steps
This description is generated using codex. I thought I created an issue but I cannot find it so this may be a duplicate.
I am trying to use
tsdownwithunbundle: truefor a package that has an aggregate entry file and separate public subpath/facade entry files.The simplified setup looks like this:
The aggregate entry is
packages/ui/index.js:The card package has its own public facade file at
packages/card/index.js:The package export map points
./cardat the generated facade path:{ "exports": { ".": "./dist/packages/ui/index.mjs", "./card": "./dist/packages/card/index.mjs" } }I have attached a sample project
tsdown-unbundle-facade-repro.zip
What is expected?
With
unbundle: true, I expected tsdown to transform the reachable module graph while preserving file-level public entry/facade modules. In this case, I expected the build output to include:The important file is
dist/packages/card/index.mjs. I expected it to preserve the public facade exportsWhat is actually happening?
Instead,
tsdownemits the aggregate root and the implementation files, but does not emit the transitive facade module:The generated root file directly imports the implementation modules:
So the root package import works but the subpath export is broken because
dist/packages/card/index.mjsdoes not exist:Any additional comments?
This is surprising because
packages/card/index.jsis directly reachable from the aggregate entry and is also a public package facade/subpath target. Since unbundle mode is described as focusing on code transformation without combining files, I expected the reachable facade module to remain present in the output rather than being bypassed.The workaround is to add packages/card/index.js as an explicit entry, but that does not scale well for a package that has many public facade/subpath modules reachable from a single aggregate entry.