Summary
Introduce a NestJS-style database integration module for PyNest, similar in spirit to NestJS dynamic modules like TypeOrmModule.forRoot(...) and TypeOrmModule.forFeature(...).
The current ORM integration encourages app code to create a global OrmProvider instance, usually in config.py, and import it directly from services. That works for small examples, but it does not feel very Nest-like and makes lifecycle, dependency injection, testing, and future repository patterns harder to model cleanly.
Current pattern
Typical app code today looks like this:
# src/config.py
config = OrmProvider(
db_type="postgresql",
config_params={...},
)
# service.py
from src.config import config
with config.get_session() as session:
...
Problems with this pattern:
- Database configuration is a global object rather than an injected dependency.
- Services import infrastructure directly instead of receiving dependencies through DI.
- DB lifecycle has to be managed manually or by app-specific provider glue.
- Sessions are manually opened in every service method.
- It is hard to support multiple DB connections, test replacement providers, or a repository-oriented API later.
- The app module does not clearly express that database infrastructure is part of the module graph.
Proposed direction
Add a framework-level DatabaseModule with a dynamic-module style API:
@Module(
imports=[
DatabaseModule.for_root(
driver="postgresql",
host="localhost",
database="default_nest_db",
user="postgres",
password="postgres",
port=5432,
),
AuthorModule,
BookModule,
],
)
class AppModule:
pass
The module would register providers such as:
DATABASE_OPTIONS
DATABASE_ENGINE
DATABASE_SESSION_FACTORY
DatabaseService
DatabaseService would own lifecycle hooks:
@Injectable
class DatabaseService(OnModuleInit, OnModuleDestroy):
def on_module_init(self):
Base.metadata.create_all(bind=self.engine)
def on_module_destroy(self):
self.engine.dispose()
def session(self):
...
App services would then receive the database dependency through DI:
@Injectable
class AuthorService:
def __init__(self, db: DatabaseService):
self.db = db
def get_authors(self):
with self.db.session() as session:
return session.query(AuthorEntity).all()
Future extension
After DatabaseModule.for_root(...), add a repository-oriented API, similar to NestJS TypeOrmModule.forFeature(...):
@Module(
imports=[DatabaseModule.for_feature([AuthorEntity])],
providers=[AuthorService],
)
class AuthorModule:
pass
Then services could receive repositories rather than raw sessions:
@Injectable
class AuthorService:
def __init__(self, authors: Repository[AuthorEntity]):
self.authors = authors
def get_authors(self):
return self.authors.find_all()
Suggested implementation phases
- Add
DatabaseModule.for_root(...) and DatabaseService while preserving backward compatibility with OrmProvider.
- Update generated templates to prefer
DatabaseModule.for_root(...) instead of global config = OrmProvider(...).
- Add tests for lifecycle behavior, DI replacement, and app startup/shutdown.
- Later, add
DatabaseModule.for_feature(...) and repository injection.
Why this matters
This would make PyNest database integration feel much closer to NestJS:
- database infrastructure becomes part of the module graph
- configuration is explicit at the app-module boundary
- lifecycle is owned by the database provider
- services use dependency injection instead of global imports
- testing becomes easier by overriding providers
- the framework gets a clean path toward repository injection
Summary
Introduce a NestJS-style database integration module for PyNest, similar in spirit to NestJS dynamic modules like
TypeOrmModule.forRoot(...)andTypeOrmModule.forFeature(...).The current ORM integration encourages app code to create a global
OrmProviderinstance, usually inconfig.py, and import it directly from services. That works for small examples, but it does not feel very Nest-like and makes lifecycle, dependency injection, testing, and future repository patterns harder to model cleanly.Current pattern
Typical app code today looks like this:
Problems with this pattern:
Proposed direction
Add a framework-level
DatabaseModulewith a dynamic-module style API:The module would register providers such as:
DATABASE_OPTIONSDATABASE_ENGINEDATABASE_SESSION_FACTORYDatabaseServiceDatabaseServicewould own lifecycle hooks:App services would then receive the database dependency through DI:
Future extension
After
DatabaseModule.for_root(...), add a repository-oriented API, similar to NestJSTypeOrmModule.forFeature(...):Then services could receive repositories rather than raw sessions:
Suggested implementation phases
DatabaseModule.for_root(...)andDatabaseServicewhile preserving backward compatibility withOrmProvider.DatabaseModule.for_root(...)instead of globalconfig = OrmProvider(...).DatabaseModule.for_feature(...)and repository injection.Why this matters
This would make PyNest database integration feel much closer to NestJS: