Files
tech-log-frontend/src/bootstrap/composition-root.ts
T

52 lines
1.7 KiB
TypeScript

import { createApplication } from "../application/create-application.ts";
import type {
ApplicationApi,
ApplicationFeatureInputs,
} from "../application/ports/in/application-api.ts";
import type { ApplicationOutputPorts } from "../application/ports/out/application-output-ports.ts";
export type CompositionRoot<Config, Release, Infrastructure> = Readonly<{
config: Config;
release: Release;
infrastructure: Infrastructure;
application: ApplicationApi;
}>;
type AdapterBundle<Infrastructure> = Readonly<{
outputPorts: ApplicationOutputPorts;
infrastructure: Infrastructure;
featureInputs?: Readonly<Partial<ApplicationFeatureInputs>>;
}>;
type CompositionFactories<Config, Release, Infrastructure> = Readonly<{
loadConfig(): Promise<Config>;
loadRelease(config: Config): Promise<Release>;
createAdapters(context: Readonly<{
config: Config;
release: Release;
}>): Promise<AdapterBundle<Infrastructure>>;
}>;
/**
* This is the only module allowed to join concrete adapters to application
* ports. Boot phases are explicit so failures can stop before product mount.
*/
export async function createCompositionRoot<Config, Release, Infrastructure>(
factories: CompositionFactories<Config, Release, Infrastructure>,
): Promise<CompositionRoot<Config, Release, Infrastructure>> {
const config = await factories.loadConfig();
const release = await factories.loadRelease(config);
const adapters = await factories.createAdapters({ config, release });
const application = createApplication(
adapters.outputPorts,
adapters.featureInputs,
);
return Object.freeze({
config,
release,
infrastructure: adapters.infrastructure,
application,
});
}