diff --git a/biome.json b/biome.json index 7b4c6a10..b170dcc5 100644 --- a/biome.json +++ b/biome.json @@ -4,8 +4,8 @@ "includes": [ "host/client_app/**", "packages/**", - "modules/*/src/*/pages/**", - "modules/*/src/*/components/**" + "modules/*/*/pages/**", + "modules/*/*/components/**" ], "ignoreUnknown": true }, diff --git a/framework/core/src/simple_module_core/__init__.py b/framework/core/simple_module_core/__init__.py similarity index 100% rename from framework/core/src/simple_module_core/__init__.py rename to framework/core/simple_module_core/__init__.py diff --git a/framework/core/src/simple_module_core/diagnostics.py b/framework/core/simple_module_core/diagnostics.py similarity index 98% rename from framework/core/src/simple_module_core/diagnostics.py rename to framework/core/simple_module_core/diagnostics.py index 28309415..4ed3eb9d 100644 --- a/framework/core/src/simple_module_core/diagnostics.py +++ b/framework/core/simple_module_core/diagnostics.py @@ -228,7 +228,10 @@ def _find_package_dir(self, package_name: str) -> Path | None: return None def _check_orphan_pages( - self, mod: ModuleBase, src_dir: Path, rendered_pages: set[str], + self, + mod: ModuleBase, + src_dir: Path, + rendered_pages: set[str], ) -> list[Diagnostic]: """Find .tsx pages that aren't referenced by any inertia.render() call.""" pages_dir = src_dir / "pages" @@ -251,7 +254,10 @@ def _check_orphan_pages( ] def _check_phantom_renders( - self, mod: ModuleBase, src_dir: Path, rendered_pages: set[str], + self, + mod: ModuleBase, + src_dir: Path, + rendered_pages: set[str], ) -> list[Diagnostic]: """Find inertia.render() calls that reference non-existent pages.""" pages_dir = src_dir / "pages" diff --git a/framework/core/src/simple_module_core/discovery.py b/framework/core/simple_module_core/discovery.py similarity index 100% rename from framework/core/src/simple_module_core/discovery.py rename to framework/core/simple_module_core/discovery.py diff --git a/framework/core/src/simple_module_core/events.py b/framework/core/simple_module_core/events.py similarity index 100% rename from framework/core/src/simple_module_core/events.py rename to framework/core/simple_module_core/events.py diff --git a/framework/core/src/simple_module_core/exceptions.py b/framework/core/simple_module_core/exceptions.py similarity index 100% rename from framework/core/src/simple_module_core/exceptions.py rename to framework/core/simple_module_core/exceptions.py diff --git a/framework/core/src/simple_module_core/feature_flags.py b/framework/core/simple_module_core/feature_flags.py similarity index 100% rename from framework/core/src/simple_module_core/feature_flags.py rename to framework/core/simple_module_core/feature_flags.py diff --git a/framework/core/src/simple_module_core/health.py b/framework/core/simple_module_core/health.py similarity index 100% rename from framework/core/src/simple_module_core/health.py rename to framework/core/simple_module_core/health.py diff --git a/framework/core/src/simple_module_core/menu.py b/framework/core/simple_module_core/menu.py similarity index 100% rename from framework/core/src/simple_module_core/menu.py rename to framework/core/simple_module_core/menu.py diff --git a/framework/core/src/simple_module_core/module.py b/framework/core/simple_module_core/module.py similarity index 100% rename from framework/core/src/simple_module_core/module.py rename to framework/core/simple_module_core/module.py diff --git a/framework/core/src/simple_module_core/permissions.py b/framework/core/simple_module_core/permissions.py similarity index 100% rename from framework/core/src/simple_module_core/permissions.py rename to framework/core/simple_module_core/permissions.py diff --git a/framework/core/src/simple_module_core/py.typed b/framework/core/simple_module_core/py.typed similarity index 100% rename from framework/core/src/simple_module_core/py.typed rename to framework/core/simple_module_core/py.typed diff --git a/framework/db/src/simple_module_db/__init__.py b/framework/db/simple_module_db/__init__.py similarity index 100% rename from framework/db/src/simple_module_db/__init__.py rename to framework/db/simple_module_db/__init__.py diff --git a/framework/db/src/simple_module_db/base.py b/framework/db/simple_module_db/base.py similarity index 100% rename from framework/db/src/simple_module_db/base.py rename to framework/db/simple_module_db/base.py diff --git a/framework/db/src/simple_module_db/deps.py b/framework/db/simple_module_db/deps.py similarity index 100% rename from framework/db/src/simple_module_db/deps.py rename to framework/db/simple_module_db/deps.py diff --git a/framework/db/src/simple_module_db/listeners.py b/framework/db/simple_module_db/listeners.py similarity index 100% rename from framework/db/src/simple_module_db/listeners.py rename to framework/db/simple_module_db/listeners.py diff --git a/framework/db/src/simple_module_db/mixins.py b/framework/db/simple_module_db/mixins.py similarity index 100% rename from framework/db/src/simple_module_db/mixins.py rename to framework/db/simple_module_db/mixins.py diff --git a/framework/db/src/simple_module_db/provider.py b/framework/db/simple_module_db/provider.py similarity index 100% rename from framework/db/src/simple_module_db/provider.py rename to framework/db/simple_module_db/provider.py diff --git a/framework/db/src/simple_module_db/py.typed b/framework/db/simple_module_db/py.typed similarity index 100% rename from framework/db/src/simple_module_db/py.typed rename to framework/db/simple_module_db/py.typed diff --git a/framework/db/src/simple_module_db/session.py b/framework/db/simple_module_db/session.py similarity index 100% rename from framework/db/src/simple_module_db/session.py rename to framework/db/simple_module_db/session.py diff --git a/framework/hosting/src/simple_module_hosting/__init__.py b/framework/hosting/simple_module_hosting/__init__.py similarity index 100% rename from framework/hosting/src/simple_module_hosting/__init__.py rename to framework/hosting/simple_module_hosting/__init__.py diff --git a/framework/hosting/src/simple_module_hosting/app_builder.py b/framework/hosting/simple_module_hosting/app_builder.py similarity index 96% rename from framework/hosting/src/simple_module_hosting/app_builder.py rename to framework/hosting/simple_module_hosting/app_builder.py index dc4c06d5..7daf3667 100644 --- a/framework/hosting/src/simple_module_hosting/app_builder.py +++ b/framework/hosting/simple_module_hosting/app_builder.py @@ -3,14 +3,13 @@ from __future__ import annotations import logging -import os from collections.abc import AsyncGenerator from contextlib import asynccontextmanager +from pathlib import Path from fastapi import APIRouter, FastAPI, Request from fastapi.exceptions import HTTPException from fastapi.staticfiles import StaticFiles -from starlette.responses import RedirectResponse from inertia import ( InertiaConfig, InertiaVersionConflictException, @@ -31,6 +30,7 @@ from simple_module_db.listeners import register_listeners from simple_module_db.session import init_db from starlette.middleware.sessions import SessionMiddleware +from starlette.responses import RedirectResponse from simple_module_hosting.health import router as health_router from simple_module_hosting.middleware import InertiaLayoutDataMiddleware, SecurityHeadersMiddleware @@ -38,6 +38,9 @@ logger = logging.getLogger(__name__) +# Resolve once: simple_module_hosting/ -> hosting/ -> framework/ -> project root +_PROJECT_ROOT = Path(__file__).resolve().parents[3] + async def _check_migrations(engine, alembic_ini_path: str = "host/alembic.ini") -> dict: """Check database migration state. Raises RuntimeError if not at head. @@ -237,8 +240,8 @@ async def _handle_http_exception(request: Request, exc: HTTPException) -> Redire app.include_router(health_router) - static_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "host", "static") - if os.path.isdir(static_dir): + static_dir = _PROJECT_ROOT / "host" / "static" + if static_dir.is_dir(): app.mount("/static", StaticFiles(directory=static_dir), name="static") return app @@ -246,17 +249,11 @@ async def _handle_http_exception(request: Request, exc: HTTPException) -> Redire def _setup_inertia(app: FastAPI, settings: Settings) -> None: """Configure fastapi-inertia with the Jinja2 template.""" - import os - from fastapi.templating import Jinja2Templates - # Find the templates directory (relative to host/) - templates_dir = os.path.join( - os.path.dirname(__file__), "..", "..", "..", "..", "host", "templates" - ) - templates_dir = os.path.abspath(templates_dir) + templates_dir = _PROJECT_ROOT / "host" / "templates" - if not os.path.isdir(templates_dir): + if not templates_dir.is_dir(): logger.warning("Templates directory not found at %s", templates_dir) return @@ -301,4 +298,3 @@ def _check_settings_registration(modules: list, added_keys: set[str]) -> None: ), ) logger.warning("%s", diag) - diff --git a/framework/hosting/src/simple_module_hosting/health.py b/framework/hosting/simple_module_hosting/health.py similarity index 100% rename from framework/hosting/src/simple_module_hosting/health.py rename to framework/hosting/simple_module_hosting/health.py diff --git a/framework/hosting/src/simple_module_hosting/inertia_deps.py b/framework/hosting/simple_module_hosting/inertia_deps.py similarity index 100% rename from framework/hosting/src/simple_module_hosting/inertia_deps.py rename to framework/hosting/simple_module_hosting/inertia_deps.py diff --git a/framework/hosting/src/simple_module_hosting/inertia_utils.py b/framework/hosting/simple_module_hosting/inertia_utils.py similarity index 100% rename from framework/hosting/src/simple_module_hosting/inertia_utils.py rename to framework/hosting/simple_module_hosting/inertia_utils.py diff --git a/framework/hosting/src/simple_module_hosting/middleware.py b/framework/hosting/simple_module_hosting/middleware.py similarity index 99% rename from framework/hosting/src/simple_module_hosting/middleware.py rename to framework/hosting/simple_module_hosting/middleware.py index 2c2f3020..c6263dcb 100644 --- a/framework/hosting/src/simple_module_hosting/middleware.py +++ b/framework/hosting/simple_module_hosting/middleware.py @@ -5,11 +5,12 @@ import secrets from typing import TYPE_CHECKING -from simple_module_hosting.permissions import expand_permissions, resolve_permissions from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint from starlette.requests import Request from starlette.responses import Response +from simple_module_hosting.permissions import expand_permissions, resolve_permissions + if TYPE_CHECKING: from simple_module_core.menu import MenuRegistry from simple_module_core.permissions import PermissionRegistry diff --git a/framework/hosting/src/simple_module_hosting/permissions.py b/framework/hosting/simple_module_hosting/permissions.py similarity index 100% rename from framework/hosting/src/simple_module_hosting/permissions.py rename to framework/hosting/simple_module_hosting/permissions.py diff --git a/framework/hosting/src/simple_module_hosting/py.typed b/framework/hosting/simple_module_hosting/py.typed similarity index 100% rename from framework/hosting/src/simple_module_hosting/py.typed rename to framework/hosting/simple_module_hosting/py.typed diff --git a/framework/hosting/src/simple_module_hosting/settings.py b/framework/hosting/simple_module_hosting/settings.py similarity index 100% rename from framework/hosting/src/simple_module_hosting/settings.py rename to framework/hosting/simple_module_hosting/settings.py diff --git a/host/client_app/pages.ts b/host/client_app/pages.ts index 9d9a5151..66ab050f 100644 --- a/host/client_app/pages.ts +++ b/host/client_app/pages.ts @@ -1,7 +1,7 @@ /** * Auto-discover all module pages via Vite's import.meta.glob. * - * Convention: modules/{name}/src/sm_{name}/pages/{PageName}.tsx + * Convention: modules/{name}/sm_{name}/pages/{PageName}.tsx * Inertia component name: "{ModuleName}/{PageName}" * * Vite code-splits each page into its own chunk automatically. @@ -11,15 +11,15 @@ type PageModule = { default: React.ComponentType> }; type PageLoader = () => Promise; -const pageModules = import.meta.glob('../../modules/*/src/*/pages/*.tsx'); +const pageModules = import.meta.glob('../../modules/*/*/pages/*.tsx'); const pages: Record = {}; for (const [filePath, loader] of Object.entries(pageModules)) { // Extract module name and page name from file path - // e.g., "../../modules/products/src/sm_products/pages/Browse.tsx" + // e.g., "../../modules/products/sm_products/pages/Browse.tsx" // -> moduleName = "Products", pageName = "Browse" - const match = filePath.match(/modules\/(\w+)\/src\/\w+\/pages\/(\w+)\.tsx$/); + const match = filePath.match(/modules\/(\w+)\/\w+\/pages\/(\w+)\.tsx$/); if (match) { const moduleName = match[1].charAt(0).toUpperCase() + match[1].slice(1); const pageName = match[2]; diff --git a/host/client_app/tsconfig.json b/host/client_app/tsconfig.json index f34b6643..5697b7b6 100644 --- a/host/client_app/tsconfig.json +++ b/host/client_app/tsconfig.json @@ -18,8 +18,8 @@ "include": [ "**/*.ts", "**/*.tsx", - "../../modules/*/src/**/*.ts", - "../../modules/*/src/**/*.tsx", + "../../modules/*/**/*.ts", + "../../modules/*/**/*.tsx", "../../packages/*/src/**/*.ts", "../../packages/*/src/**/*.tsx" ] diff --git a/modules/auth/src/sm_auth/__init__.py b/modules/auth/sm_auth/__init__.py similarity index 100% rename from modules/auth/src/sm_auth/__init__.py rename to modules/auth/sm_auth/__init__.py diff --git a/modules/auth/src/sm_auth/contracts/__init__.py b/modules/auth/sm_auth/contracts/__init__.py similarity index 100% rename from modules/auth/src/sm_auth/contracts/__init__.py rename to modules/auth/sm_auth/contracts/__init__.py diff --git a/modules/auth/src/sm_auth/contracts/schemas.py b/modules/auth/sm_auth/contracts/schemas.py similarity index 100% rename from modules/auth/src/sm_auth/contracts/schemas.py rename to modules/auth/sm_auth/contracts/schemas.py diff --git a/modules/auth/src/sm_auth/deps.py b/modules/auth/sm_auth/deps.py similarity index 100% rename from modules/auth/src/sm_auth/deps.py rename to modules/auth/sm_auth/deps.py diff --git a/modules/auth/src/sm_auth/endpoints/__init__.py b/modules/auth/sm_auth/endpoints/__init__.py similarity index 100% rename from modules/auth/src/sm_auth/endpoints/__init__.py rename to modules/auth/sm_auth/endpoints/__init__.py diff --git a/modules/auth/src/sm_auth/endpoints/api.py b/modules/auth/sm_auth/endpoints/api.py similarity index 100% rename from modules/auth/src/sm_auth/endpoints/api.py rename to modules/auth/sm_auth/endpoints/api.py diff --git a/modules/auth/src/sm_auth/middleware.py b/modules/auth/sm_auth/middleware.py similarity index 100% rename from modules/auth/src/sm_auth/middleware.py rename to modules/auth/sm_auth/middleware.py diff --git a/modules/auth/src/sm_auth/module.py b/modules/auth/sm_auth/module.py similarity index 100% rename from modules/auth/src/sm_auth/module.py rename to modules/auth/sm_auth/module.py diff --git a/modules/auth/src/sm_auth/oauth.py b/modules/auth/sm_auth/oauth.py similarity index 100% rename from modules/auth/src/sm_auth/oauth.py rename to modules/auth/sm_auth/oauth.py diff --git a/modules/auth/src/sm_auth/py.typed b/modules/auth/sm_auth/py.typed similarity index 100% rename from modules/auth/src/sm_auth/py.typed rename to modules/auth/sm_auth/py.typed diff --git a/modules/auth/src/sm_auth/settings.py b/modules/auth/sm_auth/settings.py similarity index 100% rename from modules/auth/src/sm_auth/settings.py rename to modules/auth/sm_auth/settings.py diff --git a/modules/dashboard/src/sm_dashboard/__init__.py b/modules/dashboard/sm_dashboard/__init__.py similarity index 100% rename from modules/dashboard/src/sm_dashboard/__init__.py rename to modules/dashboard/sm_dashboard/__init__.py diff --git a/modules/dashboard/src/sm_dashboard/endpoints/__init__.py b/modules/dashboard/sm_dashboard/endpoints/__init__.py similarity index 100% rename from modules/dashboard/src/sm_dashboard/endpoints/__init__.py rename to modules/dashboard/sm_dashboard/endpoints/__init__.py diff --git a/modules/dashboard/src/sm_dashboard/endpoints/views.py b/modules/dashboard/sm_dashboard/endpoints/views.py similarity index 100% rename from modules/dashboard/src/sm_dashboard/endpoints/views.py rename to modules/dashboard/sm_dashboard/endpoints/views.py diff --git a/modules/dashboard/src/sm_dashboard/module.py b/modules/dashboard/sm_dashboard/module.py similarity index 100% rename from modules/dashboard/src/sm_dashboard/module.py rename to modules/dashboard/sm_dashboard/module.py diff --git a/modules/dashboard/src/sm_dashboard/pages/Home.tsx b/modules/dashboard/sm_dashboard/pages/Home.tsx similarity index 100% rename from modules/dashboard/src/sm_dashboard/pages/Home.tsx rename to modules/dashboard/sm_dashboard/pages/Home.tsx diff --git a/modules/dashboard/src/sm_dashboard/pages/Landing.tsx b/modules/dashboard/sm_dashboard/pages/Landing.tsx similarity index 100% rename from modules/dashboard/src/sm_dashboard/pages/Landing.tsx rename to modules/dashboard/sm_dashboard/pages/Landing.tsx diff --git a/modules/dashboard/src/sm_dashboard/py.typed b/modules/dashboard/sm_dashboard/py.typed similarity index 100% rename from modules/dashboard/src/sm_dashboard/py.typed rename to modules/dashboard/sm_dashboard/py.typed diff --git a/modules/products/src/sm_products/__init__.py b/modules/products/sm_products/__init__.py similarity index 100% rename from modules/products/src/sm_products/__init__.py rename to modules/products/sm_products/__init__.py diff --git a/modules/products/src/sm_products/contracts/__init__.py b/modules/products/sm_products/contracts/__init__.py similarity index 100% rename from modules/products/src/sm_products/contracts/__init__.py rename to modules/products/sm_products/contracts/__init__.py diff --git a/modules/products/src/sm_products/contracts/schemas.py b/modules/products/sm_products/contracts/schemas.py similarity index 100% rename from modules/products/src/sm_products/contracts/schemas.py rename to modules/products/sm_products/contracts/schemas.py diff --git a/modules/products/src/sm_products/contracts/service.py b/modules/products/sm_products/contracts/service.py similarity index 100% rename from modules/products/src/sm_products/contracts/service.py rename to modules/products/sm_products/contracts/service.py diff --git a/modules/products/src/sm_products/deps.py b/modules/products/sm_products/deps.py similarity index 100% rename from modules/products/src/sm_products/deps.py rename to modules/products/sm_products/deps.py diff --git a/modules/products/src/sm_products/endpoints/__init__.py b/modules/products/sm_products/endpoints/__init__.py similarity index 100% rename from modules/products/src/sm_products/endpoints/__init__.py rename to modules/products/sm_products/endpoints/__init__.py diff --git a/modules/products/src/sm_products/endpoints/api.py b/modules/products/sm_products/endpoints/api.py similarity index 100% rename from modules/products/src/sm_products/endpoints/api.py rename to modules/products/sm_products/endpoints/api.py diff --git a/modules/products/src/sm_products/endpoints/views.py b/modules/products/sm_products/endpoints/views.py similarity index 100% rename from modules/products/src/sm_products/endpoints/views.py rename to modules/products/sm_products/endpoints/views.py diff --git a/modules/products/src/sm_products/models.py b/modules/products/sm_products/models.py similarity index 100% rename from modules/products/src/sm_products/models.py rename to modules/products/sm_products/models.py diff --git a/modules/products/src/sm_products/module.py b/modules/products/sm_products/module.py similarity index 100% rename from modules/products/src/sm_products/module.py rename to modules/products/sm_products/module.py diff --git a/modules/products/src/sm_products/pages/Browse.tsx b/modules/products/sm_products/pages/Browse.tsx similarity index 100% rename from modules/products/src/sm_products/pages/Browse.tsx rename to modules/products/sm_products/pages/Browse.tsx diff --git a/modules/products/src/sm_products/pages/Create.tsx b/modules/products/sm_products/pages/Create.tsx similarity index 100% rename from modules/products/src/sm_products/pages/Create.tsx rename to modules/products/sm_products/pages/Create.tsx diff --git a/modules/products/src/sm_products/pages/Edit.tsx b/modules/products/sm_products/pages/Edit.tsx similarity index 100% rename from modules/products/src/sm_products/pages/Edit.tsx rename to modules/products/sm_products/pages/Edit.tsx diff --git a/modules/products/src/sm_products/py.typed b/modules/products/sm_products/py.typed similarity index 100% rename from modules/products/src/sm_products/py.typed rename to modules/products/sm_products/py.typed diff --git a/modules/products/src/sm_products/service.py b/modules/products/sm_products/service.py similarity index 100% rename from modules/products/src/sm_products/service.py rename to modules/products/sm_products/service.py diff --git a/modules/products/src/sm_products/validation.ts b/modules/products/sm_products/validation.ts similarity index 100% rename from modules/products/src/sm_products/validation.ts rename to modules/products/sm_products/validation.ts diff --git a/pyproject.toml b/pyproject.toml index 5a8d3060..7ff75274 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,12 +36,12 @@ ignore = [ [tool.ty.environment] extra-paths = [ - "framework/core/src", - "framework/db/src", - "framework/hosting/src", - "modules/auth/src", - "modules/dashboard/src", - "modules/products/src", + "framework/core", + "framework/db", + "framework/hosting", + "modules/auth", + "modules/dashboard", + "modules/products", "host", ]