Reproduction link or steps
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 the root export at the aggregate file and the ./card subpath export at the card facade:
{
"exports": {
".": "./dist/packages/ui/index.mjs",
"./card": "./dist/packages/card/index.mjs"
}
}
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
What is actually happening?
The important file is dist/packages/card/index.mjs. I expected it to preserve the public facade exports, something equivalent to:
export { default as Card } from './components/card.mjs';
export { BigCard } from './components/content-card.mjs';
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:
import { Card } from 'tsdown-unbundle-facade-repro';
But the subpath export is broken because dist/packages/card/index.mjs
tsdown-unbundle-facade-repro.zip
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
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 the root export at the aggregate file and the
./cardsubpath export at the card facade:{ "exports": { ".": "./dist/packages/ui/index.mjs", "./card": "./dist/packages/card/index.mjs" } }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:What is actually happening?
The important file is
dist/packages/card/index.mjs. I expected it to preserve the public facade exports, something equivalent to:Instead, tsdown emits 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.mjstsdown-unbundle-facade-repro.zip
does 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.