Modules¶
Modules are the main extension mechanism in ChaCC API. A module contributes models, routes, services, configuration, and tests while the backbone handles startup, migration, dependency resolution, and mounting.
Module layout¶
my_module/
module_meta.json
requirements.txt
my_module_src/
__init__.py
main.py
models.py
routes.py
context_factory.py
run_tests.py
tests/
__init__.py
test_module.py
README.md
.gitignore
module_meta.json¶
| Field | Required | Description |
|---|---|---|
name |
Yes | Machine-readable module name. |
display_name |
No | Human-readable name shown in module records. |
version |
No | Module version. |
author |
No | Author or organization. |
description |
No | Module description. |
entry_point |
Yes | Python path to setup function, for example my_module_src.main:setup_plugin. |
base_path_prefix |
No | Default API prefix, for example /billing. |
tags |
No | FastAPI documentation tags. |
dependencies_file |
No | Requirements file name, usually requirements.txt. |
required_chacc_version |
No | Minimum ChaCC version. |
license |
No | Module license. |
homepage |
No | Module homepage. |
Setup function¶
A module entry point must expose a callable setup function.
from fastapi import APIRouter
from chacc_api import BackboneContext
def setup_plugin(context: BackboneContext):
router = APIRouter(prefix="/items", tags=["Items"])
@router.get("/")
async def list_items():
return {"items": []}
return router
The setup function may be synchronous or asynchronous. It receives
BackboneContext and must return a FastAPI APIRouter.
Models¶
Models should inherit from ChaCCBaseModel and use @register_model.
from chacc_api import ChaCCBaseModel, register_model
from sqlalchemy import Column, String
@register_model
class Item(ChaCCBaseModel):
__tablename__ = "items"
name = Column(String, nullable=False)
ChaCCBaseModel adds:
| Field | Type | Purpose |
|---|---|---|
id |
Integer |
Primary key. |
uuid |
GUID |
Cross-database UUID value. |
created_at |
DateTime |
Creation timestamp. |
updated_at |
DateTime |
Last update timestamp. |
deleted_at |
DateTime |
Soft-delete timestamp. |
Routes¶
Use the database dependency from the module context or directly from ChaCC API.
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from chacc_api import get_db
router = APIRouter()
@router.get("/ping")
async def ping(db: Session = Depends(get_db)):
return {"ok": True}
Services¶
Modules can share behavior through BackboneContext.
def verify_token(token: str):
return token == "example"
def setup_plugin(context):
context.register_service("token_verifier", verify_token)
return router
Another module can retrieve it:
Dependencies¶
Put Python dependencies in requirements.txt. ChaCC resolves dependencies before
extracting or enabling modules.
Build and deploy¶
chacc create my_module
chacc run server --dev
chacc build plugins/my_module
chacc deploy my_module.chacc
The build command creates a ZIP archive named after the module unless an output filename is provided.
Development mode vs production mode¶
| Mode | Source directory | Behavior |
|---|---|---|
| Development | plugins/ |
Loads modules from source directories with optional hot reload. |
| Production | .modules_installed/ |
Loads enabled modules from extracted archives. |
Best practices¶
- Keep module names lowercase with underscores.
- Use one
APIRouterper module. - Put database models in importable Python files so model discovery can find
@register_model. - Avoid circular imports by using
context.get_service()instead of direct module imports. - Store module-specific secrets as
{MODULE_NAME}_{KEY}in.env. - Restart the backbone after installing, enabling, disabling, or uninstalling a module.