Dynamic modules
Let's start directly with and example. We are going to create ConfigModule
like ConfigModule
from NestJs.
Python
from dataclasses import dataclass
from os import path, getcwd
from typing import Union, Annotated
from dotenv import dotenv_values
from nestipy.common import Module, Injectable
from nestipy.dynamic_module import ConfigurableModuleBuilder
from nestipy.ioc import Inject
@dataclass
class ConfigOption:
dir: str = getcwd()
ConfigurableModuleClass, MODULE_OPTION_TOKEN = ConfigurableModuleBuilder[ConfigOption]().build()
@Injectable()
class ConfigService:
_config: Annotated[ConfigOption, Inject(MODULE_OPTION_TOKEN)]
_envs: dict = {}
def __init__(self):
file = path.join(self._config.dir, '.env')
_envs: dict = dotenv_values(file)
def get(self, key: str) -> Union[str, None]:
if key in self._envs.keys():
return self._envs.get(key)
return None
@Module(
providers=[ConfigService],
exports=[ConfigService]
)
class ConfigModule(ConfigurableModuleClass):
pass
So, let's view how to use it.
Python
from nestipy.common import Module
@Module(
imports=[
ConfigModule.register() # we can define ConfigOption in register
# ConfigModule.register(options=ConfigOption(dir=getcwd()))
],
...
)
class AppModule:
pass
Now, we can use ConfigModule
in controller or a service provider by injecting it.
Python
from nestipy.ioc import Inject
from typing import Annotated
from nestipy.common import Controller
@Controller('cats')
class CatsController:
config_service: Annotated[ConfigService, Inject()]
Inside service,
Python
from typing import Annotated
from nestipy.common import Injectable
from nestipy.ioc import Inject
@Injectable()
class CatsService:
config_service: Annotated[ConfigService, Inject()]
Using it inside async factory.
Python
from dataclasses import dataclass
from typing import Annotated
from nestipy.dynamic_module import ConfigurableModuleBuilder, NestipyModule
from nestipy.ioc import Inject
from nestipy.common import ConfigModule, ConfigService
from nestipy.common import Module
@dataclass
class DatabaseConfigOption:
host: str
password: str
user: str
port: int = 3306
ConfigurableModuleClass, MODULE_OPTION_TOKEN = ConfigurableModuleBuilder[DatabaseConfigOption]().set_method(
'for_root').build()
@Module()
class DatabaseModule(ConfigurableModuleClass, NestipyModule):
option: Annotated[DatabaseConfigOption, Inject(MODULE_OPTION_TOKEN)]
def on_startup(self):
# start connection to database by using option
pass
def on_shutdown(self):
# stop connection to database
pass
async def database_config_factory(config: Annotated[ConfigService, Inject()]) -> DatabaseConfigOption:
return DatabaseConfigOption(
host=config.get('DB_HOST'),
port=int(config.get('DB_PORT')),
password=config.get('DB_PASSWORD'),
user=config.get('DB_USER')
)
@Module(
imports=[
ConfigModule.register(),
DatabaseModule.for_root_async(
factory=database_config_factory,
inject=[ConfigService]
)
]
)
class AppModule:
pass
Note: We can inject service directly inside Module
if we want to use DatabaseService
with lifecycle hook
inside `DatabaseModule
Take a look here for an example.
Support us
Nestipy is a project released under the MIT license, meaning it's open source and freely available for use and modification. Its development thrives with the generous contributions of these fantastic individuals.