Module Visibility
By default every provider lives in one application-wide container, so a service can inject anything registered anywhere, whether or not
its module imports the other. That is convenient and forgiving; it also hides wrong imports/exports until you move code around.
Strict mode turns imports and exports into a real boundary, as in NestJS:
app = AustialFactory.create(AppModule, strict_modules=True)
ctx = await AustialFactory.create_application_context(AppModule, strict_modules=True)A provider (or controller) may then inject only:
- what its own module provides;
- what the modules it imports export — a module can re-export an imported module by listing that module in its own
exports; - what a
@Globalmodule exports.
Framework tokens (ModuleRef, DiscoveryService, REQUEST, INQUIRER, …) are always visible. Anything else raises
ModuleVisibilityError when it is built:
SneakyService (module SneakyModule) can't inject Secrets: Secrets is provided by a module that SneakyModule doesn't import,
or that doesn't export it. Import the module and add Secrets to its `exports=[...]` (or make the module @Global).@Module(providers=[Mailer, Secrets], exports=[Mailer]) # Secrets stays private
class MailModule: ...
@Module(imports=[MailModule], providers=[OrdersService]) # OrdersService may inject Mailer, not Secrets
class OrdersModule: ...Providers that no module declares (classes the container auto-registers) are not checked. Turn strict mode on in your test or CI configuration first to find the violations, then in production once they are fixed.
app.select(Module)#
Narrow lookups to one module, like app.select(CatsModule):
cats = app.select(CatsModule)
cats.get(CatsService) # same as app.get
cats.get(Mailer, strict=True) # must be visible from CatsModule, else ModuleVisibilityError
cats.select(MailModule)Selecting a module that is not part of the application raises KeyError.
Inspecting the module graph#
graph = app.get_module_graph() # a ModuleGraph
graph.to_dict() # {"modules": [{"name", "imports", "providers", "controllers", "exports", "global"}, ...]}
graph.to_mermaid() # a Mermaid flowchart; an arrow A --> B means A imports BThe same from the shell, without starting the app:
austial graph # mermaid, for src.app.app_module:AppModule
austial graph src.app.app_module:AppModule --format jsonPaste the Mermaid output into any Mermaid renderer (GitHub renders it in a fenced mermaid block) to see your architecture.