Skip to content

feat(workspace-plugin): let export-maps-sync preserve hand authored asset subpaths - #36673

Open
Ray Knight (ArrayKnight) wants to merge 1 commit into
microsoft:masterfrom
ArrayKnight:fix/export-maps-sync-static-subpaths-36655
Open

feat(workspace-plugin): let export-maps-sync preserve hand authored asset subpaths#36673
Ray Knight (ArrayKnight) wants to merge 1 commit into
microsoft:masterfrom
ArrayKnight:fix/export-maps-sync-static-subpaths-36655

Conversation

@ArrayKnight

@ArrayKnight Ray Knight (ArrayKnight) commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

export-maps-sync rebuilds a project's entire exports map from its declared entry points and keeps nothing else, so any subpath the generator cannot derive from a source file — a compiled stylesheet, a raw .css source, a wildcard asset subpath — is silently deleted on the next nx sync, with no diagnostic. The first sign is a consumer's failed import. Measured on a package with 151 export keys, 4 of them asset subpaths: with subpathEntryPoints declared, sync still dropped exactly the two .css keys.

This adds metadata.exportMap.staticSubpaths — a list of keys the generator explicitly does not own. Only the keys are declared; the entries stay hand-authored in package.json and are read back verbatim on every sync, so there is no second copy of the paths to drift. Two hardening changes come with it: a declared key with nothing to preserve now throws, naming the key (the silent-deletion failure mode becomes a loud one), and key emission runs through one canonical ordering pass (. first, ./package.json last, the rest alphabetical). Eleven unit tests are added in the plugin's existing style; on the real workspace a second nx sync is a no-op and nx sync:check reports up to date before and after the change, so no existing package moves.

Fixes #36655.

Extracted from #36656 per maintainer request — each in-tree fix from that PR as an isolated change.

…sset subpaths

The sync generator rebuilds a project's whole `exports` map from its declared
entry points and keeps nothing else, so any subpath it cannot derive from a
source file is a subpath it silently deletes on the next `nx sync`. That is
fine for packages whose map is entirely TypeScript, and fatal for one shipping
a compiled stylesheet (`./styles.css`) or a raw `.css` source published for a
consumer's Tailwind `@source` scan (`./variants.css`) - today the only way to
keep those is to stay out of the generator's scope by staying `private`.

Adds `metadata.exportMap.staticSubpaths`: a list of export keys the generator
does not own. Only the keys are declared in `project.json`; the entries stay
hand authored in `package.json` next to the `files` array that ships them, and
are read back verbatim on every sync, so there is no second copy of the paths
to drift. A key with no matching entry, or one the generator already derives
from source, throws with the key named.

Key emission now runs through a single ordering pass - `"."` first,
`"./package.json"` last, everything else alphabetical - so static and generated
subpaths land in the same predictable place. Existing packages are unaffected:
their generated subpaths were already emitted sorted, and `nx sync:check`
reports the workspace up to date before and after.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013wmpBCYJpDJCLXcScCWz1i
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: export-maps-sync silently deletes any export-map key it cannot derive from a source entry point

1 participant