diff --git a/framework/cli/simple_module_cli/templates/host/Makefile b/framework/cli/simple_module_cli/templates/host/Makefile index 8ec1d554..ca64c1bd 100644 --- a/framework/cli/simple_module_cli/templates/host/Makefile +++ b/framework/cli/simple_module_cli/templates/host/Makefile @@ -21,4 +21,4 @@ migrate: uv run alembic upgrade head gen-pages: - uv run sm gen-pages --host-dir=client_app + uv run python -m simple_module_hosting gen-pages --host-dir=client_app diff --git a/framework/cli/simple_module_cli/templates/host/pyproject.toml.tpl b/framework/cli/simple_module_cli/templates/host/pyproject.toml.tpl index 1801e92c..c1282d99 100644 --- a/framework/cli/simple_module_cli/templates/host/pyproject.toml.tpl +++ b/framework/cli/simple_module_cli/templates/host/pyproject.toml.tpl @@ -7,11 +7,12 @@ dependencies = [ "simple_module_core>=1.0,<2.0", "simple_module_db>=1.0,<2.0", "simple_module_hosting>=1.0,<2.0", + "simple_module_settings>=1.0,<2.0", "alembic>=1.13", "uvicorn[standard]>=0.34", {{MODULE_DEPS}} ] -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" +# Host is an application, not a distributable package. +[tool.uv] +package = false diff --git a/framework/core/simple_module_core/diagnostics/_js_workspace.py b/framework/core/simple_module_core/diagnostics/_js_workspace.py index 2ae8dff1..508c086f 100644 --- a/framework/core/simple_module_core/diagnostics/_js_workspace.py +++ b/framework/core/simple_module_core/diagnostics/_js_workspace.py @@ -12,11 +12,18 @@ def check_js_workspace_files(mod: ModuleBase, src_dir: Path) -> list[Diagnostic]: - """Warn when a module ships .tsx pages but is missing npm workspace files.""" + """Warn when a module ships .tsx pages but is missing npm workspace files. + + Wheel-installed modules under ``site-packages/`` are skipped — the + install location is package-manager-owned, so any file we'd ask the + user to create there gets obliterated on the next reinstall. + """ + module_dir = src_dir.parent + if "site-packages" in module_dir.parts: + return [] pages_dir = src_dir / "pages" if not pages_dir.exists() or not any(pages_dir.rglob("*.tsx")): return [] - module_dir = src_dir.parent return [ Diagnostic( level=DiagnosticLevel.WARNING, diff --git a/framework/core/tests/test_module_diagnostics.py b/framework/core/tests/test_module_diagnostics.py index 4691ddee..1dbe6662 100644 --- a/framework/core/tests/test_module_diagnostics.py +++ b/framework/core/tests/test_module_diagnostics.py @@ -112,6 +112,17 @@ async def test_fires_only_for_missing_file(self, tmp_path: Path): assert results[0].code == "SM017" assert "tsconfig.json" in (results[0].file or "") + async def test_silent_when_module_lives_in_site_packages(self, tmp_path: Path): + site_packages = tmp_path / ".venv" / "lib" / "python3.12" / "site-packages" + src_dir = site_packages / "orders" + (src_dir / "pages").mkdir(parents=True) + (src_dir / "pages" / "Browse.tsx").write_text("export default function Browse() {}") + mod = _FakeModule(meta=_FakeMeta(name="Orders")) + + results = check_js_workspace_files(mod, src_dir) # pyright: ignore[reportArgumentType] + + assert results == [] + def _mk_page(src_dir: Path, filename: str, body: str) -> Path: pages = src_dir / "pages" diff --git a/framework/hosting/simple_module_hosting/_inertia_setup.py b/framework/hosting/simple_module_hosting/_inertia_setup.py index 98a1abb3..1084770b 100644 --- a/framework/hosting/simple_module_hosting/_inertia_setup.py +++ b/framework/hosting/simple_module_hosting/_inertia_setup.py @@ -26,19 +26,27 @@ def setup_inertia( ) -> InertiaConfig | None: """Configure fastapi-inertia and attach the dependency factory to app.state. - The host's own ``host/templates`` directory is first in the search path so - it can override module-contributed templates. Each installed module - contributes additional directories via ``ModuleBase.template_dirs()``. + Two host layouts are supported: ``host/templates`` (the framework's + own host package) and ``templates`` at the project root (what + ``sm new`` produces). The first one found wins so it can override + module-contributed templates. """ from fastapi.templating import Jinja2Templates - host_templates = project_root / "host" / "templates" + candidate_dirs = [ + project_root / "host" / "templates", + project_root / "templates", + ] directories: list[Path] = [] - if host_templates.is_dir(): + host_templates = next((p for p in candidate_dirs if p.is_dir()), None) + if host_templates is not None: directories.append(host_templates) else: - logger.warning("Host templates directory not found at %s", host_templates) + logger.warning( + "Host templates directory not found (looked in %s)", + ", ".join(str(p) for p in candidate_dirs), + ) for mod in modules: for path in mod.template_dirs(): diff --git a/modules/background_tasks/pyproject.toml b/modules/background_tasks/pyproject.toml index 0c15db0d..b20b3186 100644 --- a/modules/background_tasks/pyproject.toml +++ b/modules/background_tasks/pyproject.toml @@ -24,6 +24,7 @@ dependencies = [ "simple_module_core==0.0.6", "simple_module_db==0.0.6", "simple_module_hosting==0.0.6", + "simple_module_settings==0.0.6", "celery[redis]>=5.4", "redis>=5", ] @@ -53,3 +54,4 @@ packages = ["background_tasks"] simple_module_core = { workspace = true } simple_module_db = { workspace = true } simple_module_hosting = { workspace = true } +simple_module_settings = { workspace = true } diff --git a/modules/file_storage/pyproject.toml b/modules/file_storage/pyproject.toml index 267b589f..833d4b99 100644 --- a/modules/file_storage/pyproject.toml +++ b/modules/file_storage/pyproject.toml @@ -24,6 +24,7 @@ dependencies = [ "simple_module_core==0.0.6", "simple_module_db==0.0.6", "simple_module_hosting==0.0.6", + "simple_module_settings==0.0.6", "aiofiles>=23", ] @@ -55,3 +56,4 @@ packages = ["file_storage"] simple_module_core = { workspace = true } simple_module_db = { workspace = true } simple_module_hosting = { workspace = true } +simple_module_settings = { workspace = true } diff --git a/modules/users/pyproject.toml b/modules/users/pyproject.toml index 196f48cd..a99d9ea3 100644 --- a/modules/users/pyproject.toml +++ b/modules/users/pyproject.toml @@ -24,7 +24,8 @@ dependencies = [ "simple_module_core==0.0.6", "simple_module_db==0.0.6", "simple_module_hosting==0.0.6", - "simple_module_auth==0.0.6", # workspace module — contracts + "simple_module_settings==0.0.6", + "simple_module_auth==0.0.6", # Pinned to a narrow range: `deps.py` relies on mutating CookieTransport # fields after construction (see reconfigure_cookie_transport in backend.py). # Bumping the major version requires re-checking those field names. @@ -60,4 +61,5 @@ packages = ["users"] simple_module_core = { workspace = true } simple_module_db = { workspace = true } simple_module_hosting = { workspace = true } +simple_module_settings = { workspace = true } simple_module_auth = { workspace = true } diff --git a/packages/ui/package.json b/packages/ui/package.json index d2cce0ce..fd01f720 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -26,6 +26,12 @@ "types": "./src/index.ts", "default": "./src/index.ts" }, + "./components/ui/*": "./src/components/ui/*.tsx", + "./components/*": "./src/components/*.tsx", + "./layouts/*": "./src/layouts/*.tsx", + "./hooks/*": "./src/hooks/*.ts", + "./lib/*": "./src/lib/*.ts", + "./styles/*": "./src/styles/*", "./*": "./src/*" }, "files": [