##// END OF EJS Templates
working on fluent configuration
cin -
r132:0866c6259285 ioc ts support
parent child
Show More
@@ -0,0 +1,17
1 import { Container } from "../Container";
2 import { ExtractDependency, ServiceRecordBuilder } from "./interfaces";
3
4 export class ConfigBuilder<S extends object, Y extends keyof S = keyof S> {
5 register<K extends Y>(name: K, builder: (t: ServiceRecordBuilder<S[K], S>) => void | Promise<void>): ConfigBuilder<S, Exclude<Y, K>>;
6 register<K extends Y, V>(name: S[K] extends ExtractDependency<V, S> ? K : never, value: V): ConfigBuilder<S, Exclude<Y, K>>;
7 register<K extends Y>(name: K, value: S[K], raw: true): ConfigBuilder<S, Exclude<Y, K>>;
8 register<K extends Y>(name: K, value: any, raw = false): ConfigBuilder<S, Exclude<Y, K>> {
9
10 return this;
11 }
12
13 apply(container: Container<S>): PromiseLike<void> {
14
15 return Promise.resolve();
16 }
17 }
@@ -0,0 +1,17
1 import { RegistrationBuilder } from "./RegistrationBuilder";
2
3 export class ConstructorBuilder<C extends new (...args: any[]) => any, S extends object>
4 extends RegistrationBuilder<InstanceType<C>, S> {
5
6 $type: C;
7
8 _params: any;
9
10 constructor(target: C, params: any) {
11 super();
12 this.$type = target;
13
14 this._params = params;
15 }
16
17 }
@@ -0,0 +1,14
1 import { RegistrationBuilder } from "./RegistrationBuilder";
2
3 export class FactoryBuilder<F extends (...args: any[]) => any, S extends object> extends RegistrationBuilder<ReturnType<F>, S> {
4 $factory: F;
5
6 _params: any;
7
8 constructor(target: F, params: any) {
9 super();
10
11 this.$factory = target;
12 this._params = params;
13 }
14 }
1 NO CONTENT: new file 100644
@@ -120,4 +120,11 export class ActivationContext<S extends
120 120 clone._service = service;
121 121 return clone;
122 122 }
123
124 /** Creates a clone for the current context, used to protect it from modifications */
125 clone(): this {
126 const clone = Object.create(this);
127 clone._services = Object.create(this._services);
128 return clone;
129 }
123 130 }
@@ -1,5 +1,6
1 1 import { TypeRegistration } from "./Configuration";
2 2 import { ExtractDependency } from "./fluent/interfaces";
3 import { RegistrationBuilder } from "./fluent/RegistrationBuilder";
3 4
4 5 export class AnnotaionBuilder<T, S extends object> {
5 6 wire<P extends any[]>(...args: P) {
@@ -22,4 +23,8 export class AnnotaionBuilder<T, S exten
22 23 throw new Error();
23 24 }
24 25
26 getRegistrationBuilder(): RegistrationBuilder<T, S> {
27 throw new Error();
28 }
29
25 30 }
@@ -19,6 +19,7 import { makeResolver } from "./Resolver
19 19 import { ICancellation } from "../interfaces";
20 20 import { isDescriptor } from "./traits";
21 21 import { LazyReferenceDescriptor } from "./LazyReferenceDescriptor";
22 import { LifetimeManager } from "./LifetimeManager";
22 23
23 24 export interface RegistrationScope<S extends object> {
24 25
@@ -74,8 +75,6 export interface LazyDependencyRegistrat
74 75 lazy: true;
75 76 }
76 77
77 type OfType<K extends keyof S, S, T> = Extract<{ [k in K]: T}, S>;
78
79 78 export type Registration<T, S extends object> = T extends primitive ? T :
80 79 (
81 80 T |
@@ -325,7 +324,6 export class Configuration<S extends obj
325 324
326 325 _makeServiceParams(data: ServiceRegistration<any, S>) {
327 326 const opts: any = {
328 owner: this._container
329 327 };
330 328 if (data.services)
331 329 opts.services = this._visitRegistrations(data.services, "services");
@@ -347,7 +345,7 export class Configuration<S extends obj
347 345 this._visit(data.params, "params");
348 346
349 347 if (data.activation) {
350 opts.activation = data.activation;
348 opts.activation = this._getLifetimeManager(data.activation);
351 349 }
352 350
353 351 if (data.cleanup)
@@ -412,4 +410,19 export class Configuration<S extends obj
412 410 this._leave();
413 411 return d;
414 412 }
413
414 _getLifetimeManager(activation: ActivationType) {
415 switch (activation) {
416 case "container":
417 return this._container.getLifetimeManager();
418 case "hierarchy":
419 return LifetimeManager.hierarchyLifetime;
420 case "context":
421 return LifetimeManager.contextLifetime;
422 case "singleton":
423 return LifetimeManager.singletonLifetime;
424 default:
425 return LifetimeManager.empty;
426 }
427 }
415 428 }
@@ -41,7 +41,7 export class LazyReferenceDescriptor<S e
41 41 return (cfg?: PartialServiceMap<S>) => {
42 42 // защищаем контекст на случай исключения в процессе
43 43 // активации
44 const ct = saved.clone();
44 const ct = cfg ? saved.clone() : saved;
45 45 try {
46 46 if (cfg) {
47 47 each(cfg, (v, k) => ct.register(k, v));
@@ -35,9 +35,10 export class LifetimeManager implements
35 35 private _cache: MapOf<any> = {};
36 36 private _destroyed = false;
37 37
38 private _pending: MapOf<boolean> = {};
39
38 40 initialize(id: string): ILifetime {
39 41 const self = this;
40 let pending = false;
41 42 return {
42 43 has() {
43 44 return (id in self._cache);
@@ -51,9 +52,9 export class LifetimeManager implements
51 52 },
52 53
53 54 enter() {
54 if (pending)
55 if (self._pending[id])
55 56 throw Error(`Cyclic reference detected: the item with the key ${id} is already activating.`);
56 pending = true;
57 self._pending[id] = true;
57 58 },
58 59
59 60 store(item: any, cleanup?: (item: any) => void) {
@@ -62,7 +63,7 export class LifetimeManager implements
62 63
63 64 if (this.has())
64 65 throw new Error(`The item with with the key ${id} already registered with this lifetime manager`);
65 pending = false;
66 delete self._pending[id];
66 67
67 68 self._cache[id] = item;
68 69
@@ -62,8 +62,6 export type InjectionSpec<T> = {
62 62 };
63 63
64 64 export interface ServiceDescriptorParams<S extends object, T, P extends any[]> {
65 owner: Container<S>;
66
67 65 lifetime?: ILifetimeManager;
68 66
69 67 params?: P;
@@ -88,12 +86,7 export class ServiceDescriptor<S extends
88 86
89 87 _lifetime = LifetimeManager.empty;
90 88
91 _owner: Container<S>;
92
93 89 constructor(opts: ServiceDescriptorParams<S, T, P>) {
94 argumentNotNull(opts && opts.owner, "opts.owner");
95
96 this._owner = opts.owner;
97 90
98 91 if (opts.lifetime)
99 92 this._lifetime = opts.lifetime;
@@ -1,13 +1,12
1 1 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
2 import { Constructor, Factory } from "../interfaces";
3 2 import { argumentNotNull, isPrimitive } from "../safe";
4 3
5 4 export interface TypeServiceDescriptorParams<S extends object, T extends object, P extends any[]> extends ServiceDescriptorParams<S, T, P> {
6 type: Constructor<T>;
5 type: new (...args: any[]) => T;
7 6 }
8 7
9 8 export class TypeServiceDescriptor<S extends object, T extends object, P extends any[]> extends ServiceDescriptor<S, T, P> {
10 _type: Constructor;
9 _type: new (...args: any[]) => T;
11 10
12 11 constructor(opts: TypeServiceDescriptorParams<S, T, P>) {
13 12 super(opts);
@@ -18,9 +17,10 export class TypeServiceDescriptor<S ext
18 17 if (this._params) {
19 18 if (this._params.length) {
20 19 this._factory = (...args) => {
21 const t = Object.create(ctor.prototype);
20 /*const t = Object.create(ctor.prototype);
22 21 const inst = ctor.apply(t, args);
23 return isPrimitive(inst) ? t : inst;
22 return isPrimitive(inst) ? t : inst;*/
23 return new ctor(...args);
24 24 };
25 25 } else {
26 26 this._factory = arg => {
@@ -1,7 +1,7
1 import { ServiceRecordBuilder, ExtractDependency, RegistrationVisitor } from "./interfaces";
1 import { ServiceRecordBuilder, ExtractDependency, RegistrationVisitor, ServiceRegistration } from "./interfaces";
2 2 import { ActivationType } from "../interfaces";
3 3
4 export class RegistrationBuilder<T, S extends object> {
4 export class RegistrationBuilder<T, S extends object> implements ServiceRegistration {
5 5 private _activationType: ActivationType = "call";
6 6
7 7 private _overrides: { [m in keyof S]?: (...args: any) => void } | undefined;
@@ -31,7 +31,7 export class RegistrationBuilder<T, S ex
31 31 return this;
32 32 }
33 33
34 visit(visitor: RegistrationVisitor<S>) {
34 visit(visitor: RegistrationVisitor) {
35 35
36 36 }
37 } No newline at end of file
37 }
@@ -37,7 +37,7 export interface ServiceRecordBuilder<T,
37 37 wired(module: ServiceModule<T, S>): RegistrationBuilder<T, S>;
38 38 }
39 39
40 export interface RegistrationVisitor<S extends object> {
40 export interface RegistrationVisitor {
41 41 visitDependency(): void;
42 42
43 43 visitObject(): void;
@@ -48,23 +48,8 export interface RegistrationVisitor<S e
48 48
49 49 }
50 50
51 export interface RegistrationBuilder<T, S extends object> {
52 override<K extends keyof S>(name: K, builder: S[K], raw: true): this;
53 override<K extends keyof S>(name: K, builder: (t: ServiceRecordBuilder<S[K], S>) => void): this;
54 override<K extends keyof S, V>(name: S[K] extends ExtractDependency<V, S> ? K : never, value: V): this;
55
56 activate(activation: ActivationType): this;
57 inject<M extends keyof T, P extends any[]>(member: T[M] extends (...params: ExtractDependency<P, S>) => any ? M : never, ...params: P): this;
58
59 visit(visitor: RegistrationVisitor<S>): void;
60 }
61
62 export interface ConstructorBuilder<C extends new (...args: any[]) => any, S extends object> extends RegistrationBuilder<InstanceType<C>, S> {
63 $type: C;
64 }
65
66 export interface FactoryBuilder<F extends (...args: any[]) => any, S extends object> extends RegistrationBuilder<ReturnType<F>, S> {
67 $factory: F;
51 export interface ServiceRegistration {
52 visit(visitor: RegistrationVisitor): void;
68 53 }
69 54
70 55 export interface ConfigBuilder<S extends object, Y extends keyof S = keyof S> {
@@ -75,7 +60,7 export interface ConfigBuilder<S extends
75 60 apply(container: Container<S>): Promise<void>;
76 61 }
77 62
78 interface ServicesDeclaration<S extends object> {
63 export interface ServicesDeclaration<S extends object> {
79 64 build<T>(this: void): ServiceRecordBuilder<T, S>;
80 65 annotate<T>(this: void): AnnotaionBuilder<T, S>;
81 66
@@ -84,5 +69,3 interface ServicesDeclaration<S extends
84 69
85 70 configure(): ConfigBuilder<S>;
86 71 }
87
88 export declare function declare<S extends object>(): ServicesDeclaration<S>;
@@ -50,4 +50,4 export interface ILifetime {
50 50 enter(): void;
51 51
52 52 store(item: any, cleanup?: (item: any) => void): void;
53 } No newline at end of file
53 }
@@ -1,7 +1,50
1 1 import { isPrimitive } from "../safe";
2 2 import { Descriptor } from "./interfaces";
3 import { ServicesDeclaration, ServiceRecordBuilder, ServiceModule, RegistrationBuilder, ExtractDependency } from "./fluent/interfaces";
4 import { AnnotaionBuilder } from "./Annotations";
5 import { FactoryBuilder } from "./fluent/FactoryBuilder";
6 import { ConstructorBuilder } from "./fluent/ConstructorBuiler";
3 7
4 8 export function isDescriptor(x: any): x is Descriptor {
5 9 return (!isPrimitive(x)) &&
6 10 (x.activate instanceof Function);
7 } No newline at end of file
11 }
12
13 export function declare<S extends object>(): ServicesDeclaration<S> {
14 return {
15 annotate<T>() {
16 return new AnnotaionBuilder<T, S>();
17 },
18 build<T>(): ServiceRecordBuilder<T, S> {
19 return {
20 factory<P extends any[], F extends (...args: ExtractDependency<P, S>) => T>(
21 target: F,
22 ...params: P
23 ): FactoryBuilder<F, S> {
24 return new FactoryBuilder(target, params);
25 },
26
27 type<P extends any[], C extends new (...args: ExtractDependency<P, S>) => T>(
28 target: C, ...params: P
29 ): ConstructorBuilder<C, S> {
30 return new ConstructorBuilder(target, params);
31 },
32
33 wired<M extends keyof any>(module: ServiceModule<T, S, M>, m?: M): RegistrationBuilder<T, S> {
34 const service = m ?
35 module[m] :
36 (module as ServiceModule<T, S>).service;
37 if (!service)
38 throw new Error("The specified module doen's provides a service annotation");
39 return service.getRegistrationBuilder();
40 }
41 };
42 },
43 configure() {
44 throw new Error();
45 },
46 dependency() {
47 throw new Error();
48 }
49 };
50 }
@@ -1,1 +1,1
1 export { ConsoleLogger as ConsoleWriter } from "./ConsoleLogger"; No newline at end of file
1 export { ConsoleLogger as ConsoleWriter } from "./ConsoleLogger";
General Comments 0
You need to be logged in to leave comments. Login now