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
- Lifetime decorators register nodes in a global registry
- On app init,
NodstarPluginwalks every route handler (including those onControllers andRouters) and inspects its type hints - For each parameter whose type is a registered node, the plugin binds a
Provideto that handler under the parameter's own name and marks itskip_validation=True, so matching is by type, not by parameter name - On startup,
@global_nodenodes are composed into an app-wide scope - Per request, a child scope is created and
@request/@per_callnodes are composed; the provider pulls the unboxed value from that scope Node[T]is an optional type-level alias that resolves toTfor type checkers; at runtime it is justAnnotated[T, Dependency(skip_validation=True)]and is treated identically to a bareTannotation
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)
| File | Size | Uploaded | |
|---|---|---|---|
| nodstar-0.1.1.tar.gz | 23.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|