##// 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
NO CONTENT: new file 100644
@@ -120,4 +120,11 export class ActivationContext<S extends
120 clone._service = service;
120 clone._service = service;
121 return clone;
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;
123 }
129 }
130 }
@@ -1,5 +1,6
1 import { TypeRegistration } from "./Configuration";
1 import { TypeRegistration } from "./Configuration";
2 import { ExtractDependency } from "./fluent/interfaces";
2 import { ExtractDependency } from "./fluent/interfaces";
3 import { RegistrationBuilder } from "./fluent/RegistrationBuilder";
3
4
4 export class AnnotaionBuilder<T, S extends object> {
5 export class AnnotaionBuilder<T, S extends object> {
5 wire<P extends any[]>(...args: P) {
6 wire<P extends any[]>(...args: P) {
@@ -22,4 +23,8 export class AnnotaionBuilder<T, S exten
22 throw new Error();
23 throw new Error();
23 }
24 }
24
25
26 getRegistrationBuilder(): RegistrationBuilder<T, S> {
27 throw new Error();
25 }
28 }
29
30 }
@@ -19,6 +19,7 import { makeResolver } from "./Resolver
19 import { ICancellation } from "../interfaces";
19 import { ICancellation } from "../interfaces";
20 import { isDescriptor } from "./traits";
20 import { isDescriptor } from "./traits";
21 import { LazyReferenceDescriptor } from "./LazyReferenceDescriptor";
21 import { LazyReferenceDescriptor } from "./LazyReferenceDescriptor";
22 import { LifetimeManager } from "./LifetimeManager";
22
23
23 export interface RegistrationScope<S extends object> {
24 export interface RegistrationScope<S extends object> {
24
25
@@ -74,8 +75,6 export interface LazyDependencyRegistrat
74 lazy: true;
75 lazy: true;
75 }
76 }
76
77
77 type OfType<K extends keyof S, S, T> = Extract<{ [k in K]: T}, S>;
78
79 export type Registration<T, S extends object> = T extends primitive ? T :
78 export type Registration<T, S extends object> = T extends primitive ? T :
80 (
79 (
81 T |
80 T |
@@ -325,7 +324,6 export class Configuration<S extends obj
325
324
326 _makeServiceParams(data: ServiceRegistration<any, S>) {
325 _makeServiceParams(data: ServiceRegistration<any, S>) {
327 const opts: any = {
326 const opts: any = {
328 owner: this._container
329 };
327 };
330 if (data.services)
328 if (data.services)
331 opts.services = this._visitRegistrations(data.services, "services");
329 opts.services = this._visitRegistrations(data.services, "services");
@@ -347,7 +345,7 export class Configuration<S extends obj
347 this._visit(data.params, "params");
345 this._visit(data.params, "params");
348
346
349 if (data.activation) {
347 if (data.activation) {
350 opts.activation = data.activation;
348 opts.activation = this._getLifetimeManager(data.activation);
351 }
349 }
352
350
353 if (data.cleanup)
351 if (data.cleanup)
@@ -412,4 +410,19 export class Configuration<S extends obj
412 this._leave();
410 this._leave();
413 return d;
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;
415 }
426 }
427 }
428 }
@@ -41,7 +41,7 export class LazyReferenceDescriptor<S e
41 return (cfg?: PartialServiceMap<S>) => {
41 return (cfg?: PartialServiceMap<S>) => {
42 // защищаем контекст на случай исключения в процессе
42 // защищаем контекст на случай исключения в процессе
43 // активации
43 // активации
44 const ct = saved.clone();
44 const ct = cfg ? saved.clone() : saved;
45 try {
45 try {
46 if (cfg) {
46 if (cfg) {
47 each(cfg, (v, k) => ct.register(k, v));
47 each(cfg, (v, k) => ct.register(k, v));
@@ -35,9 +35,10 export class LifetimeManager implements
35 private _cache: MapOf<any> = {};
35 private _cache: MapOf<any> = {};
36 private _destroyed = false;
36 private _destroyed = false;
37
37
38 private _pending: MapOf<boolean> = {};
39
38 initialize(id: string): ILifetime {
40 initialize(id: string): ILifetime {
39 const self = this;
41 const self = this;
40 let pending = false;
41 return {
42 return {
42 has() {
43 has() {
43 return (id in self._cache);
44 return (id in self._cache);
@@ -51,9 +52,9 export class LifetimeManager implements
51 },
52 },
52
53
53 enter() {
54 enter() {
54 if (pending)
55 if (self._pending[id])
55 throw Error(`Cyclic reference detected: the item with the key ${id} is already activating.`);
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 store(item: any, cleanup?: (item: any) => void) {
60 store(item: any, cleanup?: (item: any) => void) {
@@ -62,7 +63,7 export class LifetimeManager implements
62
63
63 if (this.has())
64 if (this.has())
64 throw new Error(`The item with with the key ${id} already registered with this lifetime manager`);
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 self._cache[id] = item;
68 self._cache[id] = item;
68
69
@@ -62,8 +62,6 export type InjectionSpec<T> = {
62 };
62 };
63
63
64 export interface ServiceDescriptorParams<S extends object, T, P extends any[]> {
64 export interface ServiceDescriptorParams<S extends object, T, P extends any[]> {
65 owner: Container<S>;
66
67 lifetime?: ILifetimeManager;
65 lifetime?: ILifetimeManager;
68
66
69 params?: P;
67 params?: P;
@@ -88,12 +86,7 export class ServiceDescriptor<S extends
88
86
89 _lifetime = LifetimeManager.empty;
87 _lifetime = LifetimeManager.empty;
90
88
91 _owner: Container<S>;
92
93 constructor(opts: ServiceDescriptorParams<S, T, P>) {
89 constructor(opts: ServiceDescriptorParams<S, T, P>) {
94 argumentNotNull(opts && opts.owner, "opts.owner");
95
96 this._owner = opts.owner;
97
90
98 if (opts.lifetime)
91 if (opts.lifetime)
99 this._lifetime = opts.lifetime;
92 this._lifetime = opts.lifetime;
@@ -1,13 +1,12
1 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
1 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
2 import { Constructor, Factory } from "../interfaces";
3 import { argumentNotNull, isPrimitive } from "../safe";
2 import { argumentNotNull, isPrimitive } from "../safe";
4
3
5 export interface TypeServiceDescriptorParams<S extends object, T extends object, P extends any[]> extends ServiceDescriptorParams<S, T, P> {
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 export class TypeServiceDescriptor<S extends object, T extends object, P extends any[]> extends ServiceDescriptor<S, T, P> {
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 constructor(opts: TypeServiceDescriptorParams<S, T, P>) {
11 constructor(opts: TypeServiceDescriptorParams<S, T, P>) {
13 super(opts);
12 super(opts);
@@ -18,9 +17,10 export class TypeServiceDescriptor<S ext
18 if (this._params) {
17 if (this._params) {
19 if (this._params.length) {
18 if (this._params.length) {
20 this._factory = (...args) => {
19 this._factory = (...args) => {
21 const t = Object.create(ctor.prototype);
20 /*const t = Object.create(ctor.prototype);
22 const inst = ctor.apply(t, args);
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 } else {
25 } else {
26 this._factory = arg => {
26 this._factory = arg => {
@@ -1,7 +1,7
1 import { ServiceRecordBuilder, ExtractDependency, RegistrationVisitor } from "./interfaces";
1 import { ServiceRecordBuilder, ExtractDependency, RegistrationVisitor, ServiceRegistration } from "./interfaces";
2 import { ActivationType } from "../interfaces";
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 private _activationType: ActivationType = "call";
5 private _activationType: ActivationType = "call";
6
6
7 private _overrides: { [m in keyof S]?: (...args: any) => void } | undefined;
7 private _overrides: { [m in keyof S]?: (...args: any) => void } | undefined;
@@ -31,7 +31,7 export class RegistrationBuilder<T, S ex
31 return this;
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 wired(module: ServiceModule<T, S>): RegistrationBuilder<T, S>;
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 visitDependency(): void;
41 visitDependency(): void;
42
42
43 visitObject(): void;
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> {
51 export interface ServiceRegistration {
52 override<K extends keyof S>(name: K, builder: S[K], raw: true): this;
52 visit(visitor: RegistrationVisitor): void;
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;
68 }
53 }
69
54
70 export interface ConfigBuilder<S extends object, Y extends keyof S = keyof S> {
55 export interface ConfigBuilder<S extends object, Y extends keyof S = keyof S> {
@@ -75,7 +60,7 export interface ConfigBuilder<S extends
75 apply(container: Container<S>): Promise<void>;
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 build<T>(this: void): ServiceRecordBuilder<T, S>;
64 build<T>(this: void): ServiceRecordBuilder<T, S>;
80 annotate<T>(this: void): AnnotaionBuilder<T, S>;
65 annotate<T>(this: void): AnnotaionBuilder<T, S>;
81
66
@@ -84,5 +69,3 interface ServicesDeclaration<S extends
84
69
85 configure(): ConfigBuilder<S>;
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 enter(): void;
50 enter(): void;
51
51
52 store(item: any, cleanup?: (item: any) => void): void;
52 store(item: any, cleanup?: (item: any) => void): void;
53 } No newline at end of file
53 }
@@ -1,7 +1,50
1 import { isPrimitive } from "../safe";
1 import { isPrimitive } from "../safe";
2 import { Descriptor } from "./interfaces";
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 export function isDescriptor(x: any): x is Descriptor {
8 export function isDescriptor(x: any): x is Descriptor {
5 return (!isPrimitive(x)) &&
9 return (!isPrimitive(x)) &&
6 (x.activate instanceof Function);
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