Metadata-Version: 2.4
Name: bazaar-contrib-server
Version: 0.3.0rc1
Summary: The Bazaar Compute server: the shell modules put their pages in, and its themes
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Dist: bazaar-core~=0.3.0rc1
Requires-Dist: bazaar-contrib-http~=0.3.0rc1
Requires-Dist: bazaar-contrib-schema~=0.3.0rc1
Requires-Dist: bazaar-contrib-storage~=0.3.0rc1
Requires-Dist: bazaar-contrib-server-database~=0.3.0rc1
Requires-Dist: bazaar-contrib-server-migrations~=0.3.0rc2
Requires-Dist: jinja2>=3.1.6
Requires-Dist: markdown-it-py>=4.2.0
Requires-Dist: markupsafe>=3.0.0
Requires-Dist: pydantic>=2.12.0
Requires-Dist: pygments>=2.20.0
Requires-Dist: python-multipart>=0.0.32
Requires-Dist: starlette>=0.48.0
Requires-Dist: tzdata>=2024.1 ; sys_platform == 'win32'
Requires-Python: >=3.15
Project-URL: Repository, https://github.com/open-bazaar/contrib-server
Description-Content-Type: text/markdown

# bazaar-contrib-server

The Bazaar Compute server itself. The `server` entry draws the shell around every module — the sidebar, the overview and the settings page — and offers `SERVER`, where modules register their pages, API and permission points, and `THEME`, where theme contribs register the looks the pages can wear. The `server-theme-night` and `server-theme-day` entries are the theme plugins it comes with: the night market and the morning market.

```toml
[[contribs]]
package = "bazaar-contrib-server~=0.3.0rc1"
[[contribs.enabled]]
entry = "server"
[[contribs.enabled]]
entry = "server-theme-night"
[[contribs.enabled]]
entry = "server-theme-day"
```

A module registers what it serves inside its lifespan; each registration holds while its context is open:

```python
import asyncio
from contextlib import asynccontextmanager

from bazaar_contrib_server import SERVER, PermissionItem, SidebarItem
from bazaar_core import Context, Contrib
from importlib.resources import files
from pathlib import Path
from starlette.routing import Route


@asynccontextmanager
async def lifespan(ctx: Context):
    server = ctx.accept(SERVER)
    pages = await server.pages("notes", __package__)

    async def home(request):
        return await pages.render(request, "notes.html")

    resources = Path(str(files(__package__))) / "resources"
    icon = await asyncio.to_thread((resources / "notes.svg").read_text)
    async with (
        server.module(
            "notes",
            ui=pages.application([Route("/", home)]),
            static=resources / "static",
            locales=resources / "locales",
        ),
        server.permission(
            PermissionItem(point="notes.view", description="notes.view.description")
        ),
        server.sidebar(
            SidebarItem(
                text="notes.title",
                icon=icon,
                path="/notes",
                permission="notes.view",
            )
        ),
    ):
        yield


notes = Contrib(accepts=[SERVER], lifespan=lifespan)
```

The icon is an SVG drawn as the design's are, with class `i` and a 24×24 view box. The module's interface is served at `/ui/notes` inside the shell at `/notes`, its API at `/api/notes` and its files at `/static/notes`. Its templates live in `resources/templates` of its package and extend `server/base.html`, which brings the theme stylesheet and the embedding script; pages of any other framework include `/static/server/theme.css` and `/static/server/embed.js` themselves. Everything behind the shell needs a login module, which registers itself with `server.login`; until one does, those pages and APIs answer 503.
