Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ All notable changes to this project are documented in this file. The format is b
seeds `optimizeDeps.esbuildOptions.nodePaths` and the framework repo (Vite 8)
seeds `optimizeDeps.rolldownOptions.resolve.modules` with the workspace
`node_modules/` as a NODE_PATH-style fallback for the dep scanner (GH issue #152).
- The `moduleBareImportResolver` Vite plugin no longer short-circuits on
`fsRoot`/`projectRoot` containment, so workspace-member modules at
`modules/<name>/<pkg>/pages/` get the same workspace-root re-resolution as
wheel-installed modules. In an npm-workspaces layout the workspace root *is*
the resolver root, so the previous early-return excluded the very modules
that need it. Cross-package bare imports (`maplibre-gl`, `pmtiles`, peer
deps) now resolve in both wheel and workspace install modes (GH issue #156).

## [0.0.1] — 2026-04-21

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ if (fs.existsSync(manifestPath)) {
}
}
}
const fsRootPrefix = fsRoot + path.sep;
const fakeWorkspaceImporter = path.join(fsRoot, 'package.json');

// CJS-only deps like `clsx`, `tailwind-merge`, `class-variance-authority`
Expand Down Expand Up @@ -158,11 +157,13 @@ function collectOptimizeIncludes(): string[] {

// Cross-package bare imports from module pages (`maplibre-gl`, `pmtiles`,
// `@inertiajs/react`, …) live in fsRoot/node_modules after `npm install`.
// But when a module's pages sit outside fsRoot — under
// `.venv/.../site-packages/<pkg>/pages/` for wheel installs — Vite's
// resolver walks up from the importer looking for node_modules and never
// reaches fsRoot/node_modules. Resolution fails with: "Failed to resolve
// import … Does the file exist?".
// But Vite's resolver walks up from the importer looking for node_modules
// and doesn't always reach fsRoot/node_modules — true for wheel installs
// under `.venv/.../site-packages/<pkg>/pages/` (outside fsRoot) AND for
// workspace-member modules at `modules/<name>/<pkg>/pages/` whose upward
// walk hits intermediate dirs without node_modules before reaching the
// hoisted workspace root. Resolution fails with: "Failed to resolve import
// … Does the file exist?".
//
// This plugin recovers by retrying any unresolved bare import from a
// module-pages importer as if the importer lived at fsRoot, which puts
Expand All @@ -184,7 +185,6 @@ function moduleBareImportResolver(): Plugin {
return null;
}
const importerPath = importer.split('?')[0];
if (importerPath.startsWith(fsRootPrefix)) return null;
if (!modulePagesPrefixes.some((prefix) => importerPath.startsWith(prefix))) {
return null;
}
Expand Down
39 changes: 39 additions & 0 deletions framework/cli/tests/test_scaffolding_host.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,42 @@ async def test_scaffold_vite_config_includes_node_paths_fallback(self, tmp_path)
assert "node_modules" in vite_config, (
"nodePaths entry must include 'node_modules' (GH issue #152)."
)

async def test_scaffold_vite_resolver_does_not_skip_workspace_modules(self, tmp_path):
"""The moduleBareImportResolver plugin must NOT short-circuit on
``fsRootPrefix`` containment.

In an npm-workspaces scaffold, ``fsRoot`` resolves to the workspace
root, which means workspace-member modules at ``modules/<name>/`` sit
*under* ``fsRoot``. An early-return gating on ``fsRootPrefix`` skips
them, leaving cross-package bare imports (`maplibre-gl`, `pmtiles`,
...) unresolved during dev-mode resolveId.

The plugin should guard only on the module-pages prefix set — the
condition that actually identifies module-page importers regardless of
whether they sit inside or outside ``fsRoot``.

Regression test for GitHub issue #156.
"""
from simple_module_cli.scaffolding import create_host

dest = tmp_path / "demo"
create_host(name="demo", dest=dest, modules=[])

vite_config = (dest / "client_app" / "vite.config.ts").read_text(encoding="utf-8")

# The resolver must still exist — the fix shouldn't remove the plugin.
assert "moduleBareImportResolver" in vite_config, (
"vite.config.ts must register the cross-package bare-import resolver."
)
# The buggy early-return must be gone (GH issue #156).
assert "startsWith(fsRootPrefix)" not in vite_config, (
"vite.config.ts must not early-return on fsRootPrefix containment — "
"in npm-workspaces mode workspace-member module pages live under "
"fsRoot and would be incorrectly skipped (GH issue #156)."
)
# The workspace-root re-resolution must still run.
assert "fakeWorkspaceImporter" in vite_config, (
"vite.config.ts must re-resolve unresolved bare imports against the "
"workspace root so hoisted node_modules wins (GH issue #156)."
)
14 changes: 7 additions & 7 deletions host/client_app/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ for (const pagesDir of Object.values(manifest)) {
}
}
}
const projectRootPrefix = projectRoot + path.sep;

// Gather every bare specifier a module's pages might import. We include
// both `dependencies` (deps the module ships its own copy of) and
Expand Down Expand Up @@ -80,11 +79,13 @@ function collectModuleDecls(): string[] {

// Cross-package bare imports from module pages (`maplibre-gl`, `pmtiles`,
// `@inertiajs/react`, …) live in the workspace-root node_modules after
// `npm install`. But when a module's pages sit outside the workspace root
// — under `.venv/.../site-packages/<pkg>/pages/` for wheel installs — Vite's
// resolver walks up from the importer looking for node_modules and never
// reaches <repo>/node_modules. Resolution fails with: "Failed to resolve
// import … Does the file exist?".
// `npm install`. But Vite's resolver walks up from the importer looking
// for node_modules and doesn't always reach <repo>/node_modules — true for
// wheel installs under `.venv/.../site-packages/<pkg>/pages/` (outside the
// project root) AND for workspace-member modules at `modules/<name>/<pkg>/
// pages/` whose upward walk hits intermediate dirs without node_modules
// before reaching the hoisted workspace root. Resolution fails with:
// "Failed to resolve import … Does the file exist?".
//
// This plugin recovers by retrying any unresolved bare import from a
// module-pages importer as if the importer lived at the workspace root,
Expand All @@ -106,7 +107,6 @@ function moduleBareImportResolver(): Plugin {
return null;
}
const importerPath = importer.split('?')[0];
if (importerPath.startsWith(projectRootPrefix)) return null;
if (!modulePagesPrefixes.some((prefix) => importerPath.startsWith(prefix))) {
return null;
}
Expand Down
Loading