Summary
@simple-module-py/ui@0.0.3's exports map can't resolve the imports its own consumers (and the built-in modules) use. The map is:
"exports": {
".": { "types": "./src/index.ts", "default": "./src/index.ts" },
"./*": "./src/*"
}Two problems compose into a hard fail:
- Extension stripping isn't applied to
exports patterns. Per the Node spec, "./*": "./src/*" resolves ./components/PageShell to ./src/components/PageShellliterally. There's no file at that exact path — the file is ./src/components/PageShell.tsx. Node/Vite won't try .tsx/.ts fallbacks once an exports field is present (unlike legacy main/module resolution). - The single wildcard collapses every depth into one rule. Even if the extension worked, the map can't distinguish
./components/* (→ .tsx) from ./hooks/* (→ .ts) from ./styles/* (→ .css). They have to be separate entries.
Reproduction
Fresh sm new 0.0.7 host with #114's deps worked around (or just trust the imports below — they're directly from the users module wheel and the @simple-module-py/ui source):
Error: The following dependencies are imported but could not be resolved:
@simple-module-py/ui/components/PageShell (-> src/components/PageShell.tsx)
@simple-module-py/ui/components/NavIcon (-> src/components/NavIcon.tsx)
@simple-module-py/ui/components/ui/button (-> src/components/ui/button.tsx)
@simple-module-py/ui/components/ui/card (-> src/components/ui/card.tsx)
@simple-module-py/ui/components/ui/input (-> src/components/ui/input.tsx)
@simple-module-py/ui/components/ui/label (-> src/components/ui/label.tsx)
@simple-module-py/ui/components/ui/badge (-> src/components/ui/badge.tsx)
@simple-module-py/ui/components/ui/checkbox (-> src/components/ui/checkbox.tsx)
@simple-module-py/ui/components/ui/alert-dialog (-> src/components/ui/alert-dialog.tsx)
@simple-module-py/ui/components/ui/table (-> src/components/ui/table.tsx)
@simple-module-py/ui/components/ui/tabs (-> src/components/ui/tabs.tsx)
@simple-module-py/ui/components/ui/select (-> src/components/ui/select.tsx)
@simple-module-py/ui/layouts/AuthenticatedLayout (-> src/layouts/AuthenticatedLayout.tsx)
@simple-module-py/ui/layouts/AuthCardShell (-> src/layouts/AuthCardShell.tsx)
Source-tree layout for context (extracted from client_app/node_modules/@simple-module-py/ui/src/):
src/
index.ts
types.ts
components/
ErrorBoundary.tsx ErrorScreen.tsx LocaleSwitcher.tsx NavIcon.tsx
PageShell.tsx
ui/
accordion.tsx alert-dialog.tsx alert.tsx ... (50+ shadcn components)
layouts/
AdminLayout.tsx AppLayout.tsx AuthCardShell.tsx
AuthenticatedLayout.tsx PublicLayout.tsx SidebarLayout.tsx
hooks/
*.ts
lib/
*.ts
styles/
*.css
Proposed fix
Replace the exports field in packages/ui/package.json with explicit per-directory wildcards that pin the file extension:
"exports": {
".": {
"types": "./src/index.ts",
"default": "./src/index.ts"
},
"./components/*": {
"types": "./src/components/*.tsx",
"default": "./src/components/*.tsx"
},
"./components/ui/*": {
"types": "./src/components/ui/*.tsx",
"default": "./src/components/ui/*.tsx"
},
"./layouts/*": {
"types": "./src/layouts/*.tsx",
"default": "./src/layouts/*.tsx"
},
"./hooks/*": {
"types": "./src/hooks/*.ts",
"default": "./src/hooks/*.ts"
},
"./lib/*": {
"types": "./src/lib/*.ts",
"default": "./src/lib/*.ts"
},
"./types": "./src/types.ts",
"./styles/*": "./src/styles/*"
}Notes:
./components/ui/* is listed after./components/*. Node picks the most-specific pattern, but listing the deeper one explicitly avoids any ambiguity in older resolvers.- This deliberately drops the
"./*": "./src/*" catch-all. With it back in, ambiguous resolutions can pick the wrong target. Anyone wanting raw access to a non-listed file should add an explicit entry. - All entries point at
.tsx/.ts source. Consumers compile via vite/tsc — there's no separate dist/ build step, which matches what the package already ships ("files": ["src", "README.md"]).
Sanity check
After the fix, import Button from '@simple-module-py/ui/components/ui/button' resolves to client_app/node_modules/@simple-module-py/ui/src/components/ui/button.tsx and Vite's React plugin compiles it as JSX.
Related
Workaround
Patch client_app/node_modules/@simple-module-py/ui/package.json after npm install (or use a postinstall script). Won't survive lockfile regeneration cleanly.
Environment
@simple-module-py/ui 0.0.3vite 6.4.2 (from current scaffold's npm install)- Node 20+
Summary
@simple-module-py/ui@0.0.3's exports map can't resolve the imports its own consumers (and the built-in modules) use. The map is:Two problems compose into a hard fail:
exportspatterns. Per the Node spec,"./*": "./src/*"resolves./components/PageShellto./src/components/PageShellliterally. There's no file at that exact path — the file is./src/components/PageShell.tsx. Node/Vite won't try.tsx/.tsfallbacks once anexportsfield is present (unlike legacymain/moduleresolution)../components/*(→.tsx) from./hooks/*(→.ts) from./styles/*(→.css). They have to be separate entries.Reproduction
Fresh
sm new0.0.7 host with #114's deps worked around (or just trust the imports below — they're directly from theusersmodule wheel and the@simple-module-py/uisource):Source-tree layout for context (extracted from
client_app/node_modules/@simple-module-py/ui/src/):Proposed fix
Replace the exports field in
packages/ui/package.jsonwith explicit per-directory wildcards that pin the file extension:Notes:
./components/ui/*is listed after./components/*. Node picks the most-specific pattern, but listing the deeper one explicitly avoids any ambiguity in older resolvers."./*": "./src/*"catch-all. With it back in, ambiguous resolutions can pick the wrong target. Anyone wanting raw access to a non-listed file should add an explicit entry..tsx/.tssource. Consumers compile via vite/tsc — there's no separate dist/ build step, which matches what the package already ships ("files": ["src", "README.md"]).Sanity check
After the fix,
import Button from '@simple-module-py/ui/components/ui/button'resolves toclient_app/node_modules/@simple-module-py/ui/src/components/ui/button.tsxand Vite's React plugin compiles it as JSX.Related
node_modulessymlinks. Independent of this; that one was about Vite's package walk-up, this one is about resolution within the package once it's found.Workaround
Patch
client_app/node_modules/@simple-module-py/ui/package.jsonafternpm install(or use a postinstall script). Won't survive lockfile regeneration cleanly.Environment
@simple-module-py/ui0.0.3vite6.4.2 (from current scaffold'snpm install)