|
|
import { ConfigurationMap, ConfigurationMapConstraint, ContainerServices, ContainerServicesConstraint, ExtractRequiredKeys, IContainerBuilder } from "../typings/interfaces";
|
|
|
import { argumentNotNull, each, isKey } from "./traits";
|
|
|
|
|
|
type ContainerExtensionConstraint<X, S> = ContainerServicesConstraint<Pick<S, keyof X & keyof S>>;
|
|
|
|
|
|
export class FluentConfiguration<S extends ContainerServicesConstraint<S>, Y extends keyof S = keyof S> {
|
|
|
|
|
|
private _builders: Partial<ConfigurationMap<ContainerServices<S>, keyof S, keyof S>> = {};
|
|
|
|
|
|
/** Adds a declaration of the services to the current config.
|
|
|
*
|
|
|
* @template D The map of the services
|
|
|
* @returns self
|
|
|
*/
|
|
|
declare<D extends ContainerExtensionConstraint<D,S>>(): FluentConfiguration<S & D, Y | keyof D> {
|
|
|
return this as unknown as FluentConfiguration<S & D, Y | keyof D>;
|
|
|
}
|
|
|
|
|
|
/** Adds compile-time information about the already provided services
|
|
|
*
|
|
|
* @template P The map of the provided services
|
|
|
* @returns self
|
|
|
*/
|
|
|
provided<P extends Pick<S, keyof P & keyof S>>(): FluentConfiguration<S & P, Exclude<Y, keyof P>> {
|
|
|
return this as unknown as FluentConfiguration<S & P, Exclude<Y, keyof P>>;
|
|
|
}
|
|
|
|
|
|
/** Register the service.
|
|
|
*
|
|
|
* @param name The name of the service
|
|
|
* @param builder The service builder
|
|
|
* @returns self
|
|
|
*/
|
|
|
register<K extends Y>(name: K, builder: ConfigurationMap<ContainerServices<S>,Y, keyof S>[K]): FluentConfiguration<S, Exclude<Y, K>>;
|
|
|
/** Registers the collection of services
|
|
|
* @param config The collection of services to register.
|
|
|
* @returns self
|
|
|
*/
|
|
|
register<X extends ConfigurationMapConstraint<ContainerServices<S>, Y, keyof X>>(config: X): FluentConfiguration<S, Exclude<Y, keyof X>>;
|
|
|
register<K extends Y>(nameOrConfig: K | ConfigurationMap<ContainerServices<S>, K, keyof S>, builder?: ConfigurationMap<ContainerServices<S>, Y, keyof S>[K]) {
|
|
|
if (isKey(nameOrConfig)) {
|
|
|
argumentNotNull(builder, "builder");
|
|
|
this._builders[nameOrConfig] = builder;
|
|
|
} else {
|
|
|
each(nameOrConfig, (v, k) => this.register(k, v));
|
|
|
}
|
|
|
|
|
|
return this; // as FluentConfiguration<S, Exclude<Y, K>>;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* This method is used to enable a compile time check of the configuration.
|
|
|
* If there are not configured services in the configuration the compiler
|
|
|
* will trigger the error.
|
|
|
*
|
|
|
* @param missing Empty object literal should always be specified.
|
|
|
* @returns self
|
|
|
*/
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
done(...args: ExtractRequiredKeys<S, Y> extends never ? [] : [services: {[ k in ExtractRequiredKeys<S, Y>]: "required"}]) {
|
|
|
//done() {
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
configure<C extends IContainerBuilder<ContainerServices<S>, keyof S>>(builder: C) {
|
|
|
each(this._builders, (v, k) => {
|
|
|
v(builder.createServiceBuilder(k));
|
|
|
});
|
|
|
return builder.build();
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|