Skip to main content

nodstar

nodnod integration for Litestar. Declare dependency lifetimes on nodes, inject into handlers by type.

Install

uv add nodstar

Requires Python 3.14+.

Usage

from nodnod import scalar_node
from litestar import Litestar, get
from nodstar import NodstarPlugin, Node, global_node, request

Define nodes

Decorate with a lifetime (@global_node, @request, @per_call) and @scalar_node:

@global_node
@scalar_node
class DatabasePool:
    @classmethod
    async def __compose__(cls) -> AsyncEngine:
        engine = create_async_engine(DATABASE_URL)
        yield engine
        await engine.dispose()


@request
@scalar_node
class DbSession:
    @classmethod
    async def __compose__(cls, pool: DatabasePool) -> AsyncSession:
        async with AsyncSession(pool) as session:
            yield session

Inject into handlers

Annotate a handler parameter with a node type — nodnod resolves the dependency graph, Litestar injects the value. Injection is by type, so the parameter can be named anything:

@get("/users")
async def get_users(session: DbSession) -> list[User]:
    return await session.scalars(select(User))

Optionally wrap the type in Node[T] for precise static typing — it resolves to T for the type checker (nodes are otherwise seen as type[T]):

@get("/users")
async def get_users(session: Node[DbSession]) -> list[User]:
    return await session.scalars(select(User))

Both forms are equivalent at runtime.

Wire up

app = Litestar(
    route_handlers=[get_users],
    plugins=[NodstarPlugin()],
)

That's it. No dependencies={...}, no manual Provide(), no container configuration.

Lifetimes

Decorator Scope Created Destroyed
@global_node App On startup On shutdown
@request Request Per HTTP request After response
@per_call Call Per handler invocation After handler

Nodes declare their own lifetime. The dependency graph is resolved automatically — a @request node can depend on a @global_node, and nodnod will pull the value from the parent scope.

How it works

  1. Lifetime decorators register nodes in a global registry
  2. On app init, NodstarPlugin walks every route handler (including those on Controllers and Routers) and inspects its type hints
  3. For each parameter whose type is a registered node, the plugin binds a Provide to that handler under the parameter's own name and marks it skip_validation=True, so matching is by type, not by parameter name
  4. On startup, @global_node nodes are composed into an app-wide scope
  5. Per request, a child scope is created and @request/@per_call nodes are composed; the provider pulls the unboxed value from that scope
  6. Node[T] is an optional type-level alias that resolves to T for type checkers; at runtime it is just Annotated[T, Dependency(skip_validation=True)] and is treated identically to a bare T annotation

Generator lifecycle

Use yield in __compose__ for setup/teardown:

@request
@scalar_node
class DbSession:
    @classmethod
    async def __compose__(cls, pool: DatabasePool) -> AsyncSession:
        async with AsyncSession(pool) as session:
            yield session
            # teardown runs when request scope closes

License

MIT

Release files for nodstar 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nodstar 0.1.1
File Size Uploaded
nodstar-0.1.1.tar.gz 23.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nodstar 0.1.1
File Interpreter ABI Platform
nodstar-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 31.7 kB

Release files / nodstar-0.1.1.tar.gz

Download URL nodstar-0.1.1.tar.gz
Size 23.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3c657811a48cae635d992b4ba68b79be0c01bcacf7be291fc644faf73d83b628
BLAKE2b-256 checksum
How to use checksums
4ae1b889e06e1a5c277da8e8fb63a88e93327fc777c050d749c1f38138aaad13
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / nodstar-0.1.1-py3-none-any.whl

Download URL nodstar-0.1.1-py3-none-any.whl
Size 7.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f51825e18308db14b3207e49475ff42e8248fbb4a4e61a965b13e92cccff471f
BLAKE2b-256 checksum
How to use checksums
3470277d4dfa67ec8eb4fc97b720efb76845c9c2b847b57f28c75edd3e1afbdf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page