Reference ========= .. contents:: On this page :local: :depth: 2 Config schema ------------- Each target has its own pydantic schema that its config files parse into: * ``be`` -- :class:`~be.config.schema.ProjectConfig` (covered in detail below). * ``be_root`` -- :class:`~be_root.config.RootConfig` (:ref:`be_root-schema`). * ``fe`` -- :class:`~fe.config.ProjectConfig` (:ref:`fe-schema`). * ``fe_root`` -- :class:`~fe_root.config.RootConfig` (:ref:`fe_root-schema`). The classes below correspond directly to the fields you write in the matching ``.jsonnet`` / ``.json`` file for that target. be config schema ^^^^^^^^^^^^^^^^ .. autoclass:: be.config.schema.ProjectConfig :members: :undoc-members: .. autoclass:: be.config.schema.AppConfig :members: :undoc-members: .. autoclass:: be.config.schema.App :members: :undoc-members: .. autoclass:: be.config.schema.ResourceConfig :members: :undoc-members: .. autoclass:: be.config.schema.OperationConfig :members: :undoc-members: .. autoclass:: be.config.schema.ModifierConfig :members: :undoc-members: .. autodata:: be.config.schema.FieldType :no-value: .. autoclass:: be.config.schema.FieldSpec :members: :undoc-members: .. autoclass:: be.config.schema.ColumnRef :members: :undoc-members: .. autoclass:: be.config.schema.AuthConfig :members: :undoc-members: .. autoclass:: be.config.schema.DatabaseConfig :members: :undoc-members: .. autodata:: be.config.schema.SamplerName :no-value: .. autodata:: be.config.schema.ExporterName :no-value: .. autoclass:: be.config.schema.TelemetryConfig :members: :undoc-members: .. autoclass:: be.config.schema.RateLimitConfig :members: :undoc-members: .. autoclass:: be.config.schema.LinksConfig :members: :undoc-members: .. autoclass:: be.config.schema.OpaConfig :members: :undoc-members: .. autoclass:: be.config.schema.CommsConfig :members: :undoc-members: .. autoclass:: be.config.schema.CommTypeConfig :members: :undoc-members: .. autoclass:: be.config.schema.CommsTargetConfig :members: :undoc-members: .. autoclass:: be.config.schema.GroupConfig :members: :undoc-members: .. autoclass:: be.config.schema.UserTemplatesConfig :members: :undoc-members: .. autoclass:: be.config.schema.TemplateSource :members: :undoc-members: .. autoclass:: be.config.schema.FilterConfig :members: :undoc-members: .. autoclass:: be.config.schema.StructuredFilterField :members: :undoc-members: .. autodata:: be.config.schema.FilterValueKind :no-value: .. autodata:: be.config.schema.FilterOperator :no-value: .. autoclass:: be.config.schema.RepresentationConfig :members: :undoc-members: .. autodata:: be.config.schema.SearchStrategy :no-value: .. autoclass:: be.config.schema.SearchConfig :members: :undoc-members: .. autoclass:: be.config.schema.OrderConfig :members: :undoc-members: .. autoclass:: be.config.schema.PaginateConfig :members: :undoc-members: Field types ^^^^^^^^^^^ The ``type`` field on :class:`~be.config.schema.FieldSpec` accepts: .. list-table:: :header-rows: 1 :widths: 15 25 30 30 * - Type - Python annotation - Used in - Notes * - ``uuid`` - ``uuid.UUID`` - request/response schemas, pk - Default for primary keys. * - ``str`` - ``str`` - schemas, action params - * - ``email`` - ``str`` - schemas - Added ``pydantic.EmailStr`` validation. * - ``int`` - ``int`` - schemas, pk - * - ``float`` - ``float`` - schemas - * - ``bool`` - ``bool`` - schemas - * - ``datetime`` - ``datetime.datetime`` - schemas - * - ``date`` - ``datetime.date`` - schemas - * - ``json`` - ``dict[str, Any]`` - schemas - * - ``nested`` - generated sub-schema class - read-op schemas (``get`` / ``list``) - Dumps a related model inline. Requires ``model`` and ``fields``; see :ref:`nested-fields` below. .. _nested-fields: Nested (related-model) fields ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A field with ``type: "nested"`` renders as an inline dump of a related SQLAlchemy model. The generator emits a scoped sub-schema (``{ParentSchema}{FieldPascal}Nested``) plus a sub-serializer, and attaches a loader to the handler's ``select(...)`` so the relationship is eagerly loaded before serialization. Keys on a nested spec: .. list-table:: :header-rows: 1 :widths: 15 85 * - Key - Meaning * - ``model`` - Dotted import path of the related SQLAlchemy class, e.g. ``"blog.models.Author"``. **Required.** * - ``fields`` - Sub-field list for the dump. Can itself contain further nested entries. **Required; must be non-empty.** * - ``many`` - ``true`` when the relationship returns a collection. The generated schema wraps the sub-type in ``list[...]`` and the serializer list-comprehends over ``obj.{field}``. * - ``load`` - Eager-loading strategy. ``"selectin"`` (default) issues one extra SELECT — safe for both scalar and collection relationships and avoids N+1. ``"joined"`` emits a single JOIN (better for one-to-one / many-to-one scalars). ``"subquery"`` uses an older correlated-subquery load. Mixes freely across nesting levels: a ``"joined"`` outer and a ``"selectin"`` inner compose as ``joinedload(A.b).selectinload(B.c)``. Nested fields are supported on read ops (``get`` / ``list``) only. Write-op request bodies (``create`` / ``update``) must use scalar fields. The ``be/fields.libsonnet`` helper library exposes a ``nested`` shortcut for common cases — see :doc:`usage` for examples. .. _be_root-schema: be_root config schema ^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: be_root.config.RootConfig :members: .. _fe-schema: fe config schema ^^^^^^^^^^^^^^^^ .. autoclass:: fe.config.ProjectConfig :members: .. _fe_root-schema: fe_root config schema ^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: fe_root.config.RootConfig :members: Built-in operations ------------------- Every built-in operation is registered under its target's own entry-point group in ``pyproject.toml``: ``be.operations`` for the ``be`` target, ``be_root.operations`` for ``be_root``, and so on. See :doc:`usage` for what each one generates and :doc:`extending` for the operation protocol. The table below covers ``be``'s built-in ops; ``be_root``, ``fe``, and ``fe_root`` each ship a single project-scope ``RootScaffold`` / ``OpenApiTsConfig`` op (see :ref:`be_root-schema`, :ref:`fe-schema`, :ref:`fe_root-schema` for the configs that drive them). .. list-table:: :header-rows: 1 :widths: 20 18 18 44 * - Name - Module - Scope - Description * - ``scaffold`` - :mod:`be.operations.scaffold` - project - Two project-scope ops live here. ``Scaffold`` always emits ``db/*_session.py``. ``AuthScaffold`` emits the ``auth/`` package when ``config.auth`` is set. * - ``get`` / ``list`` / ``create`` / ``update`` / ``delete`` - :mod:`be.operations.get`, :mod:`~be.operations.list`, :mod:`~be.operations.create`, :mod:`~be.operations.update`, :mod:`~be.operations.delete` - resource - The five CRUD endpoints. Each op lives in its own module alongside the FastAPI renderer for its output. * - ``action`` - :mod:`be.operations.action` - resource - Custom action endpoints: ``POST /{pk}/{slug}`` for per-instance actions, ``POST /{slug}`` for collection-level actions. * - ``auth`` - :mod:`be.operations.auth` - resource - Cross-cutting augmenter. Appends ``current_user`` dependency to every CRUD / action handler when ``config.auth`` is set. * - ``router`` - :mod:`be.operations.routing` - app - Emits ``routes/__init__.py`` for one app, aggregating every resource router via ``include_router``. * - ``project_router`` - :mod:`be.operations.routing` - project - Multi-app projects only. Emits the top-level ``routes/__init__.py`` that mounts each app at its prefix. Generated file layout --------------------- The table below summarises every file be can produce. Paths are relative to the ``--out`` directory (or to the config's ``package_prefix`` when ``--out`` is omitted). ``{module}`` is the app's ``module`` config field. ``{name}`` is the lowercase, snake-cased model name. .. list-table:: :header-rows: 1 :widths: 50 35 15 * - Path - Produced by - Overwrite * - ``db/__init__.py`` - ``scaffold`` - Yes * - ``db/{db_key}_session.py`` (or ``db/session.py``) - ``scaffold`` - Yes * - ``auth/__init__.py`` - ``scaffold`` - Yes * - ``auth/dependencies.py`` - ``scaffold`` - Yes * - ``auth/router.py`` - ``scaffold`` - Yes * - ``{module}/schemas/{name}.py`` - ``get`` / ``list`` / ``create`` / ``update`` - Yes * - ``{module}/serializers/{name}.py`` - ``get`` / ``list`` - Yes * - ``{module}/routes/{name}.py`` - CRUD + ``action`` - Yes * - ``{module}/routes/__init__.py`` - ``router`` - Yes * - ``{module}/tests/test_{name}.py`` - CRUD + ``action`` (when ``generate_tests: true``) - Yes * - ``routes/__init__.py`` - ``project_router`` - Yes Every file is overwritten on every generation run. codegen API ------------- Targets ^^^^^^^ .. autoclass:: codegen.target.Target :members: .. autofunction:: codegen.target.discover_targets .. autoexception:: codegen.errors.CLIError :members: :undoc-members: .. autoexception:: codegen.errors.ConfigError :members: :undoc-members: .. autoexception:: codegen.errors.GenerationError :members: :undoc-members: Engine ^^^^^^ .. autoclass:: codegen.engine.Engine :members: .. autoclass:: codegen.engine.BuildContext :members: Operations ^^^^^^^^^^ .. autofunction:: codegen.operation.operation .. autofunction:: codegen.operation.load_registry .. autoclass:: codegen.operation.OperationMeta :members: .. autoclass:: codegen.operation.EmptyOptions :members: .. autoclass:: codegen.operation.OperationRegistry :members: Scopes ^^^^^^ .. autoclass:: codegen.scope.Scope :members: .. autoclass:: codegen.scope.ScopeTree :members: .. autoclass:: codegen.scope.Scoped :members: .. autofunction:: codegen.scope.discover_scopes .. data:: codegen.scope.PROJECT The root scope -- always present in every generation run. Typed outputs ^^^^^^^^^^^^^ Every operation's ``build`` method returns instances of the types below. Framework-agnostic types live in ``codegen.outputs``; FastAPI-specific output dataclasses live in ``be.operations.types``. .. autoclass:: codegen.outputs.StaticFile :members: :undoc-members: .. autoclass:: be.operations.types.RouteHandler :members: :undoc-members: .. autoclass:: be.operations.types.RouteParam :members: :undoc-members: .. autoclass:: be.operations.types.SchemaClass :members: :undoc-members: .. autoclass:: be.operations.types.Field :members: :undoc-members: .. autoclass:: be.operations.types.EnumClass :members: :undoc-members: .. autoclass:: be.operations.types.SerializerFn :members: :undoc-members: .. autoclass:: be.operations.types.TestCase :members: :undoc-members: .. autoclass:: be.operations.types.RouterMount :members: :undoc-members: .. autoclass:: be.operations.types.FieldsOptions :members: :undoc-members: Render registry ^^^^^^^^^^^^^^^ .. autoclass:: codegen.render.RenderRegistry :members: .. autoclass:: codegen.render.RenderCtx :members: .. autoclass:: codegen.store.BuildStore :members: .. autoclass:: codegen.render.FileFragment :members: .. autoclass:: codegen.render.SnippetFragment :members: .. autoclass:: codegen.render.Fragment :members: .. data:: codegen.render.registry Process-wide :class:`RenderRegistry` populated at import time. Output ^^^^^^ .. autoclass:: codegen.spec.GeneratedFile :members: .. autofunction:: codegen.output.write_files Naming and imports ^^^^^^^^^^^^^^^^^^ .. autoclass:: codegen.naming.Name :members: .. autofunction:: codegen.naming.prefix_import .. autoclass:: codegen.imports.ImportCollector :members: .. autofunction:: codegen.imports.format_imports Jinja environment ^^^^^^^^^^^^^^^^^ .. autofunction:: codegen.env.create_jinja_env .. autofunction:: codegen.env.render_template Stdlib reference ---------------- The following ``.libsonnet`` files ship inside the be package and are importable from any config file using the ``be/`` prefix. ``be/auth/jwt.libsonnet`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Configures JWT authentication. .. code-block:: jsonnet local auth = import 'be/auth/jwt.libsonnet'; auth.jwt({ secret_env: "JWT_SECRET", algorithm: "HS256", token_url: "/auth/token", exclude_paths: ["/docs", "/openapi.json", "/health"], verify_credentials_fn: "myapp.auth.verify_credentials", }) To supply a custom ``get_current_user`` dependency instead of the generated JWT flow, set ``get_current_user_fn`` to a dotted import path. In that case ``verify_credentials_fn`` is not required. ``be/db/databases.libsonnet`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Configures async PostgreSQL connections. .. code-block:: jsonnet local db = import 'be/db/databases.libsonnet'; db.postgres("primary", { url_env: "DATABASE_URL", default: true, echo: false, pool_size: 5, max_overflow: 10, pool_timeout: 30, pool_recycle: -1, pool_pre_ping: true, }) Resources that omit ``db_key`` use the database with ``default: true``. pgqueuer integration ^^^^^^^^^^^^^^^^^^^^ be does not scaffold pgqueuer wiring. See :doc:`pgqueuer` for the full guide — the two helpers in :mod:`ingot.queue` (:func:`ingot.queue.get_queue` for transactional-outbox enqueue, :func:`ingot.queue.open_worker_driver` for the SQLAlchemy→asyncpg DSN bridge), the worker-factory pattern, and how to run the worker with pgqueuer's own CLI.