diff --git a/src/main/ts/di/ActivationContext.ts b/src/main/ts/di/ActivationContext.ts --- a/src/main/ts/di/ActivationContext.ts +++ b/src/main/ts/di/ActivationContext.ts @@ -120,4 +120,11 @@ export class ActivationContext { wire

(...args: P) { @@ -22,4 +23,8 @@ export class AnnotaionBuilder { + throw new Error(); + } + } diff --git a/src/main/ts/di/Configuration.ts b/src/main/ts/di/Configuration.ts --- a/src/main/ts/di/Configuration.ts +++ b/src/main/ts/di/Configuration.ts @@ -19,6 +19,7 @@ import { makeResolver } from "./Resolver import { ICancellation } from "../interfaces"; import { isDescriptor } from "./traits"; import { LazyReferenceDescriptor } from "./LazyReferenceDescriptor"; +import { LifetimeManager } from "./LifetimeManager"; export interface RegistrationScope { @@ -74,8 +75,6 @@ export interface LazyDependencyRegistrat lazy: true; } -type OfType = Extract<{ [k in K]: T}, S>; - export type Registration = T extends primitive ? T : ( T | @@ -325,7 +324,6 @@ export class Configuration) { const opts: any = { - owner: this._container }; if (data.services) opts.services = this._visitRegistrations(data.services, "services"); @@ -347,7 +345,7 @@ export class Configuration) => { // защищаем контекст на случай исключения в процессе // активации - const ct = saved.clone(); + const ct = cfg ? saved.clone() : saved; try { if (cfg) { each(cfg, (v, k) => ct.register(k, v)); diff --git a/src/main/ts/di/LifetimeManager.ts b/src/main/ts/di/LifetimeManager.ts --- a/src/main/ts/di/LifetimeManager.ts +++ b/src/main/ts/di/LifetimeManager.ts @@ -35,9 +35,10 @@ export class LifetimeManager implements private _cache: MapOf = {}; private _destroyed = false; + private _pending: MapOf = {}; + initialize(id: string): ILifetime { const self = this; - let pending = false; return { has() { return (id in self._cache); @@ -51,9 +52,9 @@ export class LifetimeManager implements }, enter() { - if (pending) + if (self._pending[id]) throw Error(`Cyclic reference detected: the item with the key ${id} is already activating.`); - pending = true; + self._pending[id] = true; }, store(item: any, cleanup?: (item: any) => void) { @@ -62,7 +63,7 @@ export class LifetimeManager implements if (this.has()) throw new Error(`The item with with the key ${id} already registered with this lifetime manager`); - pending = false; + delete self._pending[id]; self._cache[id] = item; diff --git a/src/main/ts/di/ServiceDescriptor.ts b/src/main/ts/di/ServiceDescriptor.ts --- a/src/main/ts/di/ServiceDescriptor.ts +++ b/src/main/ts/di/ServiceDescriptor.ts @@ -62,8 +62,6 @@ export type InjectionSpec = { }; export interface ServiceDescriptorParams { - owner: Container; - lifetime?: ILifetimeManager; params?: P; @@ -88,12 +86,7 @@ export class ServiceDescriptor; - constructor(opts: ServiceDescriptorParams) { - argumentNotNull(opts && opts.owner, "opts.owner"); - - this._owner = opts.owner; if (opts.lifetime) this._lifetime = opts.lifetime; diff --git a/src/main/ts/di/TypeServiceDescriptor.ts b/src/main/ts/di/TypeServiceDescriptor.ts --- a/src/main/ts/di/TypeServiceDescriptor.ts +++ b/src/main/ts/di/TypeServiceDescriptor.ts @@ -1,13 +1,12 @@ import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor"; -import { Constructor, Factory } from "../interfaces"; import { argumentNotNull, isPrimitive } from "../safe"; export interface TypeServiceDescriptorParams extends ServiceDescriptorParams { - type: Constructor; + type: new (...args: any[]) => T; } export class TypeServiceDescriptor extends ServiceDescriptor { - _type: Constructor; + _type: new (...args: any[]) => T; constructor(opts: TypeServiceDescriptorParams) { super(opts); @@ -18,9 +17,10 @@ export class TypeServiceDescriptor { - const t = Object.create(ctor.prototype); + /*const t = Object.create(ctor.prototype); const inst = ctor.apply(t, args); - return isPrimitive(inst) ? t : inst; + return isPrimitive(inst) ? t : inst;*/ + return new ctor(...args); }; } else { this._factory = arg => { diff --git a/src/main/ts/di/fluent/ConfigBuilder.ts b/src/main/ts/di/fluent/ConfigBuilder.ts new file mode 100644 --- /dev/null +++ b/src/main/ts/di/fluent/ConfigBuilder.ts @@ -0,0 +1,17 @@ +import { Container } from "../Container"; +import { ExtractDependency, ServiceRecordBuilder } from "./interfaces"; + +export class ConfigBuilder { + register(name: K, builder: (t: ServiceRecordBuilder) => void | Promise): ConfigBuilder>; + register(name: S[K] extends ExtractDependency ? K : never, value: V): ConfigBuilder>; + register(name: K, value: S[K], raw: true): ConfigBuilder>; + register(name: K, value: any, raw = false): ConfigBuilder> { + + return this; + } + + apply(container: Container): PromiseLike { + + return Promise.resolve(); + } +} diff --git a/src/main/ts/di/fluent/ConstructorBuiler.ts b/src/main/ts/di/fluent/ConstructorBuiler.ts new file mode 100644 --- /dev/null +++ b/src/main/ts/di/fluent/ConstructorBuiler.ts @@ -0,0 +1,17 @@ +import { RegistrationBuilder } from "./RegistrationBuilder"; + +export class ConstructorBuilder any, S extends object> + extends RegistrationBuilder, S> { + + $type: C; + + _params: any; + + constructor(target: C, params: any) { + super(); + this.$type = target; + + this._params = params; + } + +} diff --git a/src/main/ts/di/fluent/FactoryBuilder.ts b/src/main/ts/di/fluent/FactoryBuilder.ts new file mode 100644 --- /dev/null +++ b/src/main/ts/di/fluent/FactoryBuilder.ts @@ -0,0 +1,14 @@ +import { RegistrationBuilder } from "./RegistrationBuilder"; + +export class FactoryBuilder any, S extends object> extends RegistrationBuilder, S> { + $factory: F; + + _params: any; + + constructor(target: F, params: any) { + super(); + + this.$factory = target; + this._params = params; + } +} diff --git a/src/main/ts/di/fluent/RegistrationBuilder.ts b/src/main/ts/di/fluent/RegistrationBuilder.ts --- a/src/main/ts/di/fluent/RegistrationBuilder.ts +++ b/src/main/ts/di/fluent/RegistrationBuilder.ts @@ -1,7 +1,7 @@ -import { ServiceRecordBuilder, ExtractDependency, RegistrationVisitor } from "./interfaces"; +import { ServiceRecordBuilder, ExtractDependency, RegistrationVisitor, ServiceRegistration } from "./interfaces"; import { ActivationType } from "../interfaces"; -export class RegistrationBuilder { +export class RegistrationBuilder implements ServiceRegistration { private _activationType: ActivationType = "call"; private _overrides: { [m in keyof S]?: (...args: any) => void } | undefined; @@ -31,7 +31,7 @@ export class RegistrationBuilder) { + visit(visitor: RegistrationVisitor) { } -} \ No newline at end of file +} diff --git a/src/main/ts/di/fluent/ServiceRecordBuilder.ts b/src/main/ts/di/fluent/ServiceRecordBuilder.ts new file mode 100644 diff --git a/src/main/ts/di/fluent/interfaces.ts b/src/main/ts/di/fluent/interfaces.ts --- a/src/main/ts/di/fluent/interfaces.ts +++ b/src/main/ts/di/fluent/interfaces.ts @@ -37,7 +37,7 @@ export interface ServiceRecordBuilder): RegistrationBuilder; } -export interface RegistrationVisitor { +export interface RegistrationVisitor { visitDependency(): void; visitObject(): void; @@ -48,23 +48,8 @@ export interface RegistrationVisitor { - override(name: K, builder: S[K], raw: true): this; - override(name: K, builder: (t: ServiceRecordBuilder) => void): this; - override(name: S[K] extends ExtractDependency ? K : never, value: V): this; - - activate(activation: ActivationType): this; - inject(member: T[M] extends (...params: ExtractDependency) => any ? M : never, ...params: P): this; - - visit(visitor: RegistrationVisitor): void; -} - -export interface ConstructorBuilder any, S extends object> extends RegistrationBuilder, S> { - $type: C; -} - -export interface FactoryBuilder any, S extends object> extends RegistrationBuilder, S> { - $factory: F; +export interface ServiceRegistration { + visit(visitor: RegistrationVisitor): void; } export interface ConfigBuilder { @@ -75,7 +60,7 @@ export interface ConfigBuilder): Promise; } -interface ServicesDeclaration { +export interface ServicesDeclaration { build(this: void): ServiceRecordBuilder; annotate(this: void): AnnotaionBuilder; @@ -84,5 +69,3 @@ interface ServicesDeclaration; } - -export declare function declare(): ServicesDeclaration; diff --git a/src/main/ts/di/interfaces.ts b/src/main/ts/di/interfaces.ts --- a/src/main/ts/di/interfaces.ts +++ b/src/main/ts/di/interfaces.ts @@ -50,4 +50,4 @@ export interface ILifetime { enter(): void; store(item: any, cleanup?: (item: any) => void): void; -} \ No newline at end of file +} diff --git a/src/main/ts/di/traits.ts b/src/main/ts/di/traits.ts --- a/src/main/ts/di/traits.ts +++ b/src/main/ts/di/traits.ts @@ -1,7 +1,50 @@ import { isPrimitive } from "../safe"; import { Descriptor } from "./interfaces"; +import { ServicesDeclaration, ServiceRecordBuilder, ServiceModule, RegistrationBuilder, ExtractDependency } from "./fluent/interfaces"; +import { AnnotaionBuilder } from "./Annotations"; +import { FactoryBuilder } from "./fluent/FactoryBuilder"; +import { ConstructorBuilder } from "./fluent/ConstructorBuiler"; export function isDescriptor(x: any): x is Descriptor { return (!isPrimitive(x)) && (x.activate instanceof Function); -} \ No newline at end of file +} + +export function declare(): ServicesDeclaration { + return { + annotate() { + return new AnnotaionBuilder(); + }, + build(): ServiceRecordBuilder { + return { + factory

) => T>( + target: F, + ...params: P + ): FactoryBuilder { + return new FactoryBuilder(target, params); + }, + + type

) => T>( + target: C, ...params: P + ): ConstructorBuilder { + return new ConstructorBuilder(target, params); + }, + + wired(module: ServiceModule, m?: M): RegistrationBuilder { + const service = m ? + module[m] : + (module as ServiceModule).service; + if (!service) + throw new Error("The specified module doen's provides a service annotation"); + return service.getRegistrationBuilder(); + } + }; + }, + configure() { + throw new Error(); + }, + dependency() { + throw new Error(); + } + }; +} diff --git a/src/main/ts/log/writers/ConsoleWriter.ts b/src/main/ts/log/writers/ConsoleWriter.ts --- a/src/main/ts/log/writers/ConsoleWriter.ts +++ b/src/main/ts/log/writers/ConsoleWriter.ts @@ -1,1 +1,1 @@ -export { ConsoleLogger as ConsoleWriter } from "./ConsoleLogger"; \ No newline at end of file +export { ConsoleLogger as ConsoleWriter } from "./ConsoleLogger";