FluentConfiguration.ts
67 lines
| 2.4 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r0 | import { DescriptorBuilder } from "./DescriptorBuilder"; | ||
|
|
r1 | import { ConfigurableKeys, ContainerServices, ConfigurableServices, RegistrationBuildersMap, RequiredKeys } from "./interfaces"; | ||
| import { ServiceContainer } from "./interfaces"; | ||||
| import { argumentNotNull, each, isKey } from "./traits"; | ||||
|
|
r0 | |||
|
|
r1 | export class FluentConfiguration<S extends object, Y extends ConfigurableKeys<S> = ConfigurableKeys<S>> { | ||
|
|
r0 | |||
|
|
r1 | _builders: Partial<RegistrationBuildersMap<S>> = {}; | ||
|
|
r0 | |||
|
|
r1 | declare<D extends Partial<Pick<S, keyof D & keyof S>>>(): FluentConfiguration<S & D, Y | ConfigurableKeys<D>> { | ||
| return this as FluentConfiguration<S & D, Y | ConfigurableKeys<D>>; | ||||
|
|
r0 | } | ||
|
|
r1 | provided<P extends Pick<S, keyof P & keyof S>>(): FluentConfiguration<S & P, Exclude<Y, keyof P>> { | ||
| return this as FluentConfiguration<S & P, Exclude<Y, keyof P>>; | ||||
| } | ||||
| register<K extends Y>(name: K, builder: RegistrationBuildersMap<S>[K]): FluentConfiguration<S, Exclude<Y, K>>; | ||||
| register<K extends Y>(config: RegistrationBuildersMap<S, K>): FluentConfiguration<S, Exclude<Y, K>>; | ||||
| register<K extends Y>(nameOrConfig: K | RegistrationBuildersMap<S, K>, builder?: RegistrationBuildersMap<S>[K]) { | ||||
| if (isKey(nameOrConfig)) { | ||||
|
|
r0 | argumentNotNull(builder, "builder"); | ||
| this._builders[nameOrConfig] = builder; | ||||
| } else { | ||||
| each(nameOrConfig, (v, k) => this.register(k, v)); | ||||
| } | ||||
|
|
r1 | return this as FluentConfiguration<S, Exclude<Y, K>>; | ||
| } | ||||
| done(missing: RequiredKeys<S, Y> extends never ? void : RequiredKeys<S, Y>) { | ||||
| if (missing !== undefined) | ||||
| throw new Error("The configuration isn't complete"); | ||||
|
|
r0 | return this; | ||
| } | ||||
|
|
r1 | apply<A extends Partial<S>>(target: ServiceContainer<A>) { | ||
|
|
r0 | |||
| let pending = 1; | ||||
|
|
r1 | const _t2 = target as ServiceContainer<S>; | ||
|
|
r0 | |||
|
|
r1 | const reject = (ex: unknown) => { throw ex; }; | ||
| const complete = () => !--pending; | ||||
|
|
r0 | |||
|
|
r1 | each(this._builders, (v, k) => { | ||
| pending++; | ||||
| const d = new DescriptorBuilder<ContainerServices<S>, NonNullable<ConfigurableServices<S>[typeof k]>>(_t2, | ||||
| result => { | ||||
| _t2.register(k, result); | ||||
| complete(); | ||||
| }, | ||||
| reject | ||||
| ); | ||||
|
|
r0 | |||
|
|
r1 | |||
| v(d); | ||||
|
|
r0 | }); | ||
|
|
r1 | if (!complete()) | ||
| throw new Error("The configuration didn't complete."); | ||||
| return _t2 as ServiceContainer<A & S>; | ||||
|
|
r0 | } | ||
| } | ||||
