Loading modules from metadata
Some more complex scenarios could require containers to be injected in a certain order. Some others could require certain dependencies to perform bindings, such as config to establish a connection to a database.
Container module metadata is provided for those purposes.
Container Module Factory Metatada
This approach uses a factory to create the module. This metadata can receive an injects property to receive injected dependencies.
import {
  Container,
  ContainerModuleBindingService,
  ContainerModuleMetadata,
} from '@cuaklabs/iocuak';
import { someContainerModuleMetadataDependency } from 'some/path';
async function entryPoint(): Promise<void> {
  const container: Container = Container.build();
  const containerModuleMetadata: ContainerModuleMetadata = {
    factory: (someServiceDependency: Dependency) => ({
      load: (containerModuleBindingService: ContainerModuleBindingService) => {
        containerModuleBindingService.bindToValue({
          serviceId: 'service-id',
          value: someServiceDependency.someValue,
        });
      }
    }),
    imports: [someContainerModuleMetadataDependency],
    injects: [Dependency],
  }
  await container.loadMetadata(containerModuleMetadata);
}
 
Optionally, a container module to be loaded can be passed instead. This is equivalent to a factory metadata with no imports and a factory with no params that returns the module.
Container Module Class Metadata
This approach receives a class which is used to create the module.
import {
  Container,
  ContainerModule,
  ContainerModuleBindingService,
  ContainerModuleMetadata,
} from '@cuaklabs/iocuak';
import { someContainerModuleMetadataDependency } from 'some/path';
@injectable()
class MyContainerModule implements ContainerModule {
  constructor(
    @inject(Dependency)
    public readonly someServiceDependency: Dependency,
  ) {}
  public load: (containerModuleBindingService: ContainerModuleBindingService) => {
    containerModuleBindingService.bindToValue({
      serviceId: 'service-id',
      value: someServiceDependency.someValue,
    });
  }
}
async function entryPoint(): Promise<void> {
  const container: Container = Container.build();
  const containerModuleMetadata: ContainerModuleMetadata = {
    imports: [someContainerModuleMetadataDependency],
    module: MyContainerModule,
  }
  await container.loadMetadata(containerModuleMetadata);
}
 
Optionally, a container module metadata class can be passed insted. This is equivalent to a metadata with the class as module and no imports.
This approach is highly inspired on NestJs modules.