##// END OF EJS Templates
intoruced initial work on ILifetimeSlot
intoruced initial work on ILifetimeSlot

File last commit:

r9:988f0f6aab67 default
r10:99a53d63fd6f default
Show More
DescriptorBuilder.ts
193 lines | 6.3 KiB | video/mp2t | TypeScriptLexer
/ src / main / ts / DescriptorBuilder.ts
cin
almost woking typings
r9 import { BuildDescriptorFn, IDescriptorBuilder, DepsMap, Resolve, DescriptorMap } from "./interfaces";
cin
working on fluent configuration
r1 import { Descriptor, ILifetime, ActivationType } from "./interfaces";
cin
almost woking typings
r9 import { DescriptorImpl } from "./DescriptorImpl";
import { contextLifetime, emptyLifetime, hierarchyLifetime, LifetimeManager, singletonLifetime } from "./LifetimeManager";
import { each, isPromise, isString, key, oid } from "./traits";
cin
initial commit
r0
cin
working on fluent configuration
r1 /**
* @template {S} Карта доступных зависимостей, как правило `ContainerServices`
* @template {T} Тип сервиса
*/
cin
almost woking typings
r9 export class DescriptorBuilder<S, T, R, U extends keyof S> implements IDescriptorBuilder<S, T, R, U> {
cin
Working on container builder
r5 private readonly _lifetimeManager: LifetimeManager;
cin
initial commit
r0 private readonly _cb: (d: Descriptor<S, T>) => void;
cin
working on fluent configuration
r1 private readonly _eb: (err: unknown) => void;
cin
initial commit
r0
cin
almost woking typings
r9 private readonly _refs: DepsMap<R>;
cin
Removed ContextResolver, added DescriptoBuilder.wants(...), dependencies are declared statically
r4
cin
almost woking typings
r9 private _lifetime = emptyLifetime<T>();
cin
initial commit
r0
cin
almost woking typings
r9 private _overrides: DescriptorMap<S>;
cin
initial commit
r0
private _cleanup?: (item: T) => void;
cin
almost woking typings
r9 private _factory?: (refs: R) => NonNullable<T>;
cin
initial commit
r0
private _pending = 1;
private _failed = false;
cin
working on fluent configuration
r1 private _finalized = false;
/**
* Creates new DescriptorBuilder. Accepts a lifetime container for resolving "container"
* lifetime.
*
cin
Working on container builder
r5 * @param lifetimeManager The lifetime container is the container where the service is to be registered.
cin
working on fluent configuration
r1 * @param cb The callback to receive the built service descriptor
* @param eb The callback to receive the error due
*/
cin
Working on container builder
r5 constructor(lifetimeManager: LifetimeManager, cb: (d: Descriptor<S, T>) => void, eb: (err: unknown) => void) {
this._lifetimeManager = lifetimeManager;
cin
initial commit
r0 this._cb = cb;
this._eb = eb;
cin
working on fluent configuration
r1 this._overrides = {};
cin
Removed ContextResolver, added DescriptoBuilder.wants(...), dependencies are declared statically
r4 this._refs = {};
cin
initial commit
r0 }
cin
almost woking typings
r9
/** Declares dependencies to be consumed in the factory method */
wants<X extends DepsMap<S> & Record<keyof R & keyof X, never>>(refs: X):
IDescriptorBuilder<S, T, R & { [k in keyof X]: Resolve<S, X[k]>; }, U> {
cin
Removed ContextResolver, added DescriptoBuilder.wants(...), dependencies are declared statically
r4
each(refs, (v, k) => this._refs[k] = v);
return this as IDescriptorBuilder<S, T, R & {
cin
almost woking typings
r9 [k in keyof X]: Resolve<S, X[k]>;
}, U>;
cin
Removed ContextResolver, added DescriptoBuilder.wants(...), dependencies are declared statically
r4 }
cin
almost woking typings
r9
/** Registers a factory method for the service */
factory(f: (refs: R) => NonNullable<T>): void {
cin
Removed ContextResolver, added DescriptoBuilder.wants(...), dependencies are declared statically
r4 this._assertBuilding();
this._factory = f;
this._finalize();
this._complete();
}
cin
initial commit
r0
cin
working on fluent configuration
r1 private _assertBuilding() {
if (this._finalized)
throw new Error("The descriptor builder is finalized");
cin
initial commit
r0 }
cin
working on fluent configuration
r1 private _finalize() {
this._finalized = true;
}
cin
initial commit
r0
cin
almost woking typings
r9 override<K extends U>(name: K, builder: BuildDescriptorFn<S, NonNullable<S[K]>, U>): this;
override<K extends U>(services: { [k in K]: BuildDescriptorFn<S, NonNullable<S[k]>, U> }): this;
override<K extends U>(nameOrServices: K | { [name in K]: BuildDescriptorFn<S, NonNullable<S[K]>, U> }, builder?: BuildDescriptorFn<S, NonNullable<S[K]>, U>): this {
cin
working on fluent configuration
r1 this._assertBuilding();
cin
initial commit
r0 const guard = (v: void | Promise<void>) => {
if (isPromise(v))
v.catch(err => this._fail(err));
};
cin
almost woking typings
r9 if (typeof nameOrServices !== "object") {
cin
initial commit
r0 if (builder) {
this._defer();
cin
almost woking typings
r9 const d = new DescriptorBuilder<S, NonNullable<S[K]>, object, U>(
cin
Working on container builder
r5 this._lifetimeManager,
cin
initial commit
r0 result => {
cin
working on fluent configuration
r1 this._overrides[nameOrServices] = result;
cin
initial commit
r0 this._complete();
},
err => this._fail(err)
);
try {
guard(builder(d));
} catch (err) {
this._fail(err);
}
}
} else {
each(nameOrServices, (v, k) => this.override(k, v));
}
return this;
}
cin
almost woking typings
r9 /** Specified the singleton lifetime for the service */
cin
initial commit
r0 lifetime(lifetime: "singleton", typeId: string): this;
cin
almost woking typings
r9 /**
* Specifies the lifetime for the service, either {@linkcode ILifetime<T>}
* object or {@linkcode ActivationType} literal.
* @param lifetime
*/
cin
working on fluent configuration
r1 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
lifetime(lifetime: ILifetime<T> | ActivationType, typeId?: string): this {
this._assertBuilding();
cin
initial commit
r0 if (isString(lifetime)) {
this._lifetime = this._resolveLifetime(lifetime, typeId);
} else {
this._lifetime = lifetime;
}
return this;
}
cin
almost woking typings
r9 /** Registers cleanup callback, used when lifetime of the instance is managed
* by the container or some external mechanism
*/
cin
initial commit
r0 cleanup(cb: (item: T) => void): this {
cin
working on fluent configuration
r1 this._assertBuilding();
cin
initial commit
r0 this._cleanup = cb;
return this;
}
cin
almost woking typings
r9 /** Registers a value as the instance of the service */
value(v: NonNullable<T>): void {
cin
working on fluent configuration
r1 this._assertBuilding();
cin
initial commit
r0 this._cb({
activate() {
return v;
}
});
cin
working on fluent configuration
r1 this._finalize();
cin
initial commit
r0 }
cin
working on fluent configuration
r1 _resolveLifetime<T>(activation: ActivationType, typeId?: string | object): ILifetime<T> {
cin
initial commit
r0 switch (activation) {
case "container":
cin
Working on container builder
r5 return this._lifetimeManager.create();
cin
initial commit
r0 case "hierarchy":
cin
almost woking typings
r9 return hierarchyLifetime();
cin
initial commit
r0 case "context":
cin
almost woking typings
r9 return contextLifetime();
cin
working on fluent configuration
r1 case "singleton": {
cin
initial commit
r0 if (!typeId)
throw Error("The singleton activation requires a typeId");
const _oid = isString(typeId) ? typeId : oid(typeId);
cin
almost woking typings
r9 return singletonLifetime(_oid);
cin
working on fluent configuration
r1 }
cin
initial commit
r0 default:
cin
almost woking typings
r9 return emptyLifetime();
cin
initial commit
r0 }
}
_defer() {
this._pending++;
}
_complete() {
if (--this._pending === 0) {
if (!this._factory)
throw new Error("The factory must be specified");
this._cb(new DescriptorImpl<S, T>({
lifetime: this._lifetime,
cin
almost woking typings
r9 factory: this._factory as (refs: Record<key, unknown>) => NonNullable<T>,
cin
initial commit
r0 overrides: this._overrides,
cleanup: this._cleanup
}));
}
}
cin
working on fluent configuration
r1 _fail(err: unknown) {
cin
initial commit
r0 if (!this._failed) {
this._failed = true;
this._eb.call(undefined, err);
}
}
}