##// END OF EJS Templates
improved interfaces and more tight type checking
cin -
r120:1b124b65514a ioc ts support
parent child
Show More
@@ -1,23 +1,23
1 import { TraceSource } from "../log/TraceSource";
1 import { TraceSource } from "../log/TraceSource";
2 import { argumentNotNull, argumentNotEmptyString, isPrimitive, each, isNull } from "../safe";
2 import { argumentNotNull, argumentNotEmptyString } from "../safe";
3 import { Descriptor, ServiceMap, PartialServiceMap } from "./interfaces";
3 import { Descriptor, ContainerProvided, ContainerServiceMap, ContainerKeys, ContainerResolve } from "./interfaces";
4 import { Container } from "./Container";
4 import { Container } from "./Container";
5 import { MapOf } from "../interfaces";
5 import { MapOf } from "../interfaces";
6
6
7 const trace = TraceSource.get("@implab/core/di/ActivationContext");
7 const trace = TraceSource.get("@implab/core/di/ActivationContext");
8
8
9 export interface ActivationContextInfo<S> {
9 export interface ActivationContextInfo<S extends object> {
10 name: string;
10 name: string;
11
11
12 service: string;
12 service: string;
13
13
14 scope: PartialServiceMap<S>;
14 scope: ContainerServiceMap<S>;
15 }
15 }
16
16
17 export class ActivationContext<S> {
17 export class ActivationContext<S extends object> {
18 _cache: MapOf<any>;
18 _cache: MapOf<any>;
19
19
20 _services: PartialServiceMap<S>;
20 _services: ContainerServiceMap<S>;
21
21
22 _stack: ActivationContextInfo<S>[];
22 _stack: ActivationContextInfo<S>[];
23
23
@@ -29,7 +29,7 export class ActivationContext<S> {
29
29
30 container: Container<S>;
30 container: Container<S>;
31
31
32 constructor(container: Container<S>, services: PartialServiceMap<S>, name?: string, cache?: object, visited?: MapOf<any>) {
32 constructor(container: Container<S>, services: ContainerServiceMap<S>, name?: string, cache?: object, visited?: MapOf<any>) {
33 argumentNotNull(container, "container");
33 argumentNotNull(container, "container");
34 argumentNotNull(services, "services");
34 argumentNotNull(services, "services");
35
35
@@ -45,11 +45,11 export class ActivationContext<S> {
45 return this._name;
45 return this._name;
46 }
46 }
47
47
48 resolve<K extends keyof S, T extends S[K]>(name: K, def?: T): T {
48 resolve<K extends ContainerKeys<S>>(name: K, def?: ContainerResolve<S, K>) {
49 const d = this._services[name];
49 const d = this._services[name];
50
50
51 if (d !== undefined) {
51 if (d !== undefined) {
52 return this.activate(d as Descriptor<S, T>, name.toString());
52 return this.activate(d, name.toString());
53 } else {
53 } else {
54 if (def !== undefined && def !== null)
54 if (def !== undefined && def !== null)
55 return def;
55 return def;
@@ -67,7 +67,7 export class ActivationContext<S> {
67 register<K extends keyof S>(name: K, service: Descriptor<S, S[K]>) {
67 register<K extends keyof S>(name: K, service: Descriptor<S, S[K]>) {
68 argumentNotEmptyString(name, "name");
68 argumentNotEmptyString(name, "name");
69
69
70 this._services[name] = service;
70 this._services[name] = service as any;
71 }
71 }
72
72
73 clone() {
73 clone() {
@@ -3,7 +3,7 import { ActivationContext } from "./Act
3 import { isPrimitive } from "../safe";
3 import { isPrimitive } from "../safe";
4 import { isDescriptor } from "./traits";
4 import { isDescriptor } from "./traits";
5
5
6 export class AggregateDescriptor<S, T> implements Descriptor<S, T> {
6 export class AggregateDescriptor<S extends object, T> implements Descriptor<S, T> {
7 _value: any;
7 _value: any;
8
8
9 constructor(value: any) {
9 constructor(value: any) {
@@ -26,10 +26,10 type ExtractDependency<D, S> = D extends
26 type WalkDependencies<D, S> = D extends primitive ? D :
26 type WalkDependencies<D, S> = D extends primitive ? D :
27 { [K in keyof D]: ExtractDependency<D[K], S> };
27 { [K in keyof D]: ExtractDependency<D[K], S> };
28
28
29 export class Builder<T, S> {
29 export class Builder<T, S extends object> {
30 declare<P extends any[]>(...args: P) {
30 declare<P extends any[]>(...args: P) {
31 return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => {
31 return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => {
32 return constructor as C & { service: Builder<T, S> };
32
33 };
33 };
34 }
34 }
35
35
@@ -54,7 +54,7 export class Builder<T, S> {
54
54
55 }
55 }
56
56
57 interface Declaration<S> {
57 interface Declaration<S extends object> {
58 define<T>(): Builder<T, S>;
58 define<T>(): Builder<T, S>;
59
59
60 dependency<K extends keyof S>(name: K, opts: { lazy: true }): Lazy<K>;
60 dependency<K extends keyof S>(name: K, opts: { lazy: true }): Lazy<K>;
@@ -63,13 +63,15 interface Declaration<S> {
63 config(): Config<S>;
63 config(): Config<S>;
64 }
64 }
65
65
66 interface ServiceModule<T, S> {
66 type ServiceModule<T, S extends object, M extends string = "service"> = {
67 service: Builder<T, S>;
67 [m in M]: Builder<T, S>;
68 }
68 };
69
69
70 interface Config<S> {
70 export interface Config<S extends object, Y extends keyof S = keyof S> {
71 register<K extends keyof S>(name: K, builder: Builder<S[K], S>): Config<Omit<S, K>>;
71 register<K extends Y>(name: K, builder: Builder<S[K], S>): Config<S, Exclude<Y, K>>;
72 register<K extends keyof S>(name: K, m: Promise<ServiceModule<S[K], S>>): Config<Omit<S, K>>;
72 register<K extends Y>(name: K, m: Promise<ServiceModule<S[K], S>>): Config<S, Exclude<Y, K>>;
73 register<K extends Y, M extends string>(name: K, m: Promise<ServiceModule<S[K], S, M>>, x: M): Config<S, Exclude<Y, K>>;
74
73 }
75 }
74
76
75 export declare function declare<S extends object>(): Declaration<S>;
77 export declare function declare<S extends object>(): Declaration<S>;
@@ -1,9 +1,11
1 import {
1 import {
2 PartialServiceMap,
2 PartialServiceMap,
3 ActivationType
3 ActivationType,
4 ContainerKeys,
5 ContainerResolve
4 } from "./interfaces";
6 } from "./interfaces";
5
7
6 import { argumentNotEmptyString, isPrimitive, isPromise, delegate, argumentOfType, argumentNotNull, get } from "../safe";
8 import { argumentNotEmptyString, isPrimitive, isPromise, delegate, argumentOfType, argumentNotNull, get, primitive } from "../safe";
7 import { AggregateDescriptor } from "./AggregateDescriptor";
9 import { AggregateDescriptor } from "./AggregateDescriptor";
8 import { ValueDescriptor } from "./ValueDescriptor";
10 import { ValueDescriptor } from "./ValueDescriptor";
9 import { Container } from "./Container";
11 import { Container } from "./Container";
@@ -14,23 +16,23 import { TraceSource } from "../log/Trac
14 import { ConfigError } from "./ConfigError";
16 import { ConfigError } from "./ConfigError";
15 import { Cancellation } from "../Cancellation";
17 import { Cancellation } from "../Cancellation";
16 import { makeResolver } from "./ResolverHelper";
18 import { makeResolver } from "./ResolverHelper";
17 import { ICancellation, Constructor, Factory } from "../interfaces";
19 import { ICancellation } from "../interfaces";
18 import { isDescriptor } from "./traits";
20 import { isDescriptor } from "./traits";
19
21
20 export interface RegistrationScope<S> {
22 export interface RegistrationScope<S extends object> {
21
23
22 /** сервисы, которые регистрируются в контексте активации и таким образом
24 /** сервисы, которые регистрируются в контексте активации и таким образом
23 * могут переопределять ранее зарегистрированные сервисы. за это свойство
25 * могут переопределять ранее зарегистрированные сервисы. за это свойство
24 * нужно платить, кроме того порядок активации будет влиять на результат
26 * нужно платить, кроме того порядок активации будет влиять на результат
25 * разрешения зависимостей.
27 * разрешения зависимостей.
26 */
28 */
27 services?: PartialServiceMap<S>;
29 services?: RegistrationMap<S>;
28 }
30 }
29
31
30 /**
32 /**
31 * Базовый интефейс конфигурации сервисов
33 * Базовый интефейс конфигурации сервисов
32 */
34 */
33 export interface ServiceRegistration<T, P, S> extends RegistrationScope<S> {
35 export interface ServiceRegistration<T, P, S extends object> extends RegistrationScope<S> {
34
36
35 activation?: ActivationType;
37 activation?: ActivationType;
36
38
@@ -41,12 +43,12 export interface ServiceRegistration<T,
41 cleanup?: ((instance: T) => void) | string;
43 cleanup?: ((instance: T) => void) | string;
42 }
44 }
43
45
44 export interface TypeRegistration<T, P extends any[], S> extends ServiceRegistration<T, P, S> {
46 export interface TypeRegistration<T, P extends any[], S extends object> extends ServiceRegistration<T, P, S> {
45 $type: string | (new (...params: P) => T);
47 $type: string | (new (...params: P) => T);
46
48
47 }
49 }
48
50
49 export interface FactoryRegistration<T, P extends any[], S> extends ServiceRegistration<T, P, S> {
51 export interface FactoryRegistration<T, P extends any[], S extends object> extends ServiceRegistration<T, P, S> {
50 $factory: string | ( (...params: P) => T);
52 $factory: string | ((...params: P) => T);
51 }
53 }
52
54
@@ -55,13 +57,27 export interface ValueRegistration<T> {
55 parse?: boolean;
57 parse?: boolean;
56 }
58 }
57
59
58 export interface DependencyRegistration<S, K extends keyof S> extends RegistrationScope<S> {
60 export interface DependencyRegistration<S extends object, K extends ContainerKeys<S> = ContainerKeys<S>> extends RegistrationScope<S> {
59 $dependency: K;
61 $dependency: K;
60 lazy?: boolean;
62 lazy?: boolean;
61 optional?: boolean;
63 optional?: boolean;
62 default?: S[K];
64 default?: ContainerResolve<S, K>;
63 }
65 }
64
66
67 export type Registration<T, S extends object> = T extends primitive ? T :
68 (
69 T |
70 { [k in keyof T]: Registration<T[k], S> } |
71 TypeRegistration<T, any, S> |
72 FactoryRegistration<T, any, S> |
73 ValueRegistration<any> |
74 DependencyRegistration<S, keyof S>
75 );
76
77 export type RegistrationMap<S extends object> = {
78 [k in keyof S]?: Registration<S[k], S>;
79 };
80
65 const _activationTypes: { [k in ActivationType]: number; } = {
81 const _activationTypes: { [k in ActivationType]: number; } = {
66 singleton: 1,
82 singleton: 1,
67 container: 2,
83 container: 2,
@@ -82,7 +98,7 export function isValueRegistration(x: a
82 return (!isPrimitive(x)) && ("$value" in x);
98 return (!isPrimitive(x)) && ("$value" in x);
83 }
99 }
84
100
85 export function isDependencyRegistration<S>(x: any): x is DependencyRegistration<S, keyof S> {
101 export function isDependencyRegistration<S extends object>(x: any): x is DependencyRegistration<S, keyof S> {
86 return (!isPrimitive(x)) && ("$dependency" in x);
102 return (!isPrimitive(x)) && ("$dependency" in x);
87 }
103 }
88
104
@@ -112,11 +128,11 async function mapAll(data: any, map?: (
112
128
113 export type ModuleResolver = (moduleName: string, ct?: ICancellation) => any;
129 export type ModuleResolver = (moduleName: string, ct?: ICancellation) => any;
114
130
115 export class Configuration<S> {
131 export class Configuration<S extends object> {
116
132
117 _hasInnerDescriptors = false;
133 _hasInnerDescriptors = false;
118
134
119 _container: Container<S>;
135 readonly _container: Container<S>;
120
136
121 _path: Array<string>;
137 _path: Array<string>;
122
138
@@ -152,13 +168,13 export class Configuration<S> {
152 );
168 );
153 }
169 }
154
170
155 async applyConfiguration(data: object, contextRequire?: any, ct = Cancellation.none) {
171 async applyConfiguration(data: RegistrationMap<S>, contextRequire?: any, ct = Cancellation.none) {
156 argumentNotNull(data, "data");
172 argumentNotNull(data, "data");
157
173
158 await this._applyConfiguration(data, await makeResolver(void (0), contextRequire), ct);
174 await this._applyConfiguration(data, await makeResolver(void (0), contextRequire), ct);
159 }
175 }
160
176
161 async _applyConfiguration(data: object, resolver?: ModuleResolver, ct = Cancellation.none) {
177 async _applyConfiguration(data: RegistrationMap<S>, resolver?: ModuleResolver, ct = Cancellation.none) {
162 trace.log("applyConfiguration");
178 trace.log("applyConfiguration");
163
179
164 this._configName = "$";
180 this._configName = "$";
@@ -213,16 +229,13 export class Configuration<S> {
213 return this._require(moduleName);
229 return this._require(moduleName);
214 }
230 }
215
231
216 async _visitRegistrations(data: any, name: string) {
232 async _visitRegistrations(data: RegistrationMap<S>, name: string) {
217 this._enter(name);
233 this._enter(name);
218
234
219 if (data.constructor &&
235 if (data.constructor &&
220 data.constructor.prototype !== Object.prototype)
236 data.constructor.prototype !== Object.prototype)
221 throw new Error("Configuration must be a simple object");
237 throw new Error("Configuration must be a simple object");
222
238
223 const o: PartialServiceMap<S> = {};
224 const keys = Object.keys(data);
225
226 const services = await mapAll(data, async (v, k) => {
239 const services = await mapAll(data, async (v, k) => {
227 const d = await this._visit(v, k.toString());
240 const d = await this._visit(v, k.toString());
228 return isDescriptor(d) ? d : new AggregateDescriptor(d);
241 return isDescriptor(d) ? d : new AggregateDescriptor(d);
@@ -298,7 +311,7 export class Configuration<S> {
298 return v;
311 return v;
299 }
312 }
300
313
301 _makeServiceParams<T, P>(data: ServiceRegistration<T, P, S>) {
314 _makeServiceParams(data: ServiceRegistration<any, any, S>) {
302 const opts: any = {
315 const opts: any = {
303 owner: this._container
316 owner: this._container
304 };
317 };
@@ -1,17 +1,17
1 import { ActivationContext } from "./ActivationContext";
1 import { ActivationContext } from "./ActivationContext";
2 import { ValueDescriptor } from "./ValueDescriptor";
2 import { ValueDescriptor } from "./ValueDescriptor";
3 import { ActivationError } from "./ActivationError";
3 import { ActivationError } from "./ActivationError";
4 import { ServiceMap, Descriptor, PartialServiceMap, ContainerServices, Resolver } from "./interfaces";
4 import { ServiceMap, Descriptor, PartialServiceMap, ContainerProvided, Resolver, ContainerServiceMap, ContainerKeys, ContainerResolve } from "./interfaces";
5 import { TraceSource } from "../log/TraceSource";
5 import { TraceSource } from "../log/TraceSource";
6 import { Configuration } from "./Configuration";
6 import { Configuration, RegistrationMap } from "./Configuration";
7 import { Cancellation } from "../Cancellation";
7 import { Cancellation } from "../Cancellation";
8 import { MapOf } from "../interfaces";
8 import { MapOf } from "../interfaces";
9 import { isDescriptor } from "./traits";
9 import { isDescriptor } from "./traits";
10
10
11 const trace = TraceSource.get("@implab/core/di/ActivationContext");
11 const trace = TraceSource.get("@implab/core/di/ActivationContext");
12
12
13 export class Container<S = any> implements Resolver<S> {
13 export class Container<S extends object = any> implements Resolver<S> {
14 readonly _services: PartialServiceMap<ContainerServices<S>>;
14 readonly _services: ContainerServiceMap<S>;
15
15
16 readonly _cache: MapOf<any>;
16 readonly _cache: MapOf<any>;
17
17
@@ -41,7 +41,7 export class Container<S = any> implemen
41 return this._parent;
41 return this._parent;
42 }
42 }
43
43
44 resolve<K extends keyof ContainerServices<S>, T extends ContainerServices<S>[K] = ContainerServices<S>[K]>(name: K, def?: T): T {
44 resolve<K extends ContainerKeys<S>>(name: K, def?: ContainerResolve<S, K>): ContainerResolve<S, K> {
45 trace.debug("resolve {0}", name);
45 trace.debug("resolve {0}", name);
46 const d = this._services[name];
46 const d = this._services[name];
47 if (d === undefined) {
47 if (d === undefined) {
@@ -53,7 +53,7 export class Container<S = any> implemen
53
53
54 const context = new ActivationContext<S>(this, this._services);
54 const context = new ActivationContext<S>(this, this._services);
55 try {
55 try {
56 return context.activate(d as Descriptor<S, T>, name.toString());
56 return context.activate(d, name.toString());
57 } catch (error) {
57 } catch (error) {
58 throw new ActivationError(name.toString(), context.getStack(), error);
58 throw new ActivationError(name.toString(), context.getStack(), error);
59 }
59 }
@@ -63,7 +63,7 export class Container<S = any> implemen
63 /**
63 /**
64 * @deprecated use resolve() method
64 * @deprecated use resolve() method
65 */
65 */
66 getService<K extends keyof S, T extends ContainerServices<S>[K] = ContainerServices<S>[K]>(name: K, def?: T) {
66 getService<K extends ContainerKeys<S>>(name: K, def?: ContainerResolve<S, K>) {
67 return this.resolve(name, def);
67 return this.resolve(name, def);
68 }
68 }
69
69
@@ -111,7 +111,7 export class Container<S = any> implemen
111 * The function which will be used to load a configuration or types for services.
111 * The function which will be used to load a configuration or types for services.
112 *
112 *
113 */
113 */
114 async configure(config: string | object, opts?: any, ct = Cancellation.none) {
114 async configure(config: string | RegistrationMap<S>, opts?: any, ct = Cancellation.none) {
115 const c = new Configuration<S>(this);
115 const c = new Configuration<S>(this);
116
116
117 if (typeof (config) === "string") {
117 if (typeof (config) === "string") {
@@ -121,7 +121,7 export class Container<S = any> implemen
121 }
121 }
122 }
122 }
123
123
124 createChildContainer<S2 extends { container?: Container<S & S2> } = S>(): Container<S & S2> {
124 createChildContainer<S2 extends object = S>(): Container<S & S2> {
125 return new Container<S & S2>(this as any);
125 return new Container<S & S2>(this as any);
126 }
126 }
127
127
@@ -1,11 +1,11
1 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
1 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
2 import { argumentNotNull, oid } from "../safe";
2 import { argumentNotNull, oid } from "../safe";
3
3
4 export interface FactoryServiceDescriptorParams<S, T, P extends any[]> extends ServiceDescriptorParams<S, T, P> {
4 export interface FactoryServiceDescriptorParams<S extends object, T, P extends any[]> extends ServiceDescriptorParams<S, T, P> {
5 factory: (...args: P) => T;
5 factory: (...args: P) => T;
6 }
6 }
7
7
8 export class FactoryServiceDescriptor<S, T, P extends any[]> extends ServiceDescriptor<S, T, P> {
8 export class FactoryServiceDescriptor<S extends object, T, P extends any[]> extends ServiceDescriptor<S, T, P> {
9 constructor(opts: FactoryServiceDescriptorParams<S, T, P>) {
9 constructor(opts: FactoryServiceDescriptorParams<S, T, P>) {
10 super(opts);
10 super(opts);
11
11
@@ -1,30 +1,26
1 import { isNull, argumentNotEmptyString, each, keys } from "../safe";
1 import { argumentNotEmptyString, each } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { ServiceMap, Descriptor, PartialServiceMap } from "./interfaces";
3 import { Descriptor, PartialServiceMap, ContainerResolve, ContainerKeys } from "./interfaces";
4 import { ActivationError } from "./ActivationError";
4 import { ActivationError } from "./ActivationError";
5
5
6 export interface ReferenceDescriptorParams<S, K extends keyof S> {
6 export interface ReferenceDescriptorParams<S extends object, K extends ContainerKeys<S>> {
7 name: K;
7 name: K;
8 lazy?: boolean;
8 lazy?: boolean;
9 optional?: boolean;
9 optional?: boolean;
10 default?: S[K];
10 default?: ContainerResolve<S, K>;
11 services?: PartialServiceMap<S>;
11 services?: PartialServiceMap<S>;
12 }
12 }
13
13
14 function defined<T>(v: T | undefined) {
14 export class ReferenceDescriptor<S extends object = any, K extends ContainerKeys<S> = ContainerKeys<S>>
15 if (v === undefined)
15 implements Descriptor<S, ContainerResolve<S, K> | ((args?: PartialServiceMap<S>) => ContainerResolve<S, K>)> {
16 throw Error();
17 return v;
18 }
19
16
20 export class ReferenceDescriptor<S = any, K extends keyof S = keyof S> implements Descriptor<S, S[K] | ((args?: PartialServiceMap<S> ) => S[K])> {
21 _name: K;
17 _name: K;
22
18
23 _lazy = false;
19 _lazy = false;
24
20
25 _optional = false;
21 _optional = false;
26
22
27 _default: S[K] | undefined;
23 _default: ContainerResolve<S, K> | undefined;
28
24
29 _services: PartialServiceMap<S>;
25 _services: PartialServiceMap<S>;
30
26
@@ -35,7 +31,7 export class ReferenceDescriptor<S = any
35 this._optional = !!opts.optional;
31 this._optional = !!opts.optional;
36 this._default = opts.default;
32 this._default = opts.default;
37
33
38 this._services = (opts.services || {}) as ServiceMap<S>;
34 this._services = (opts.services || {}) as PartialServiceMap<S>;
39 }
35 }
40
36
41 activate(context: ActivationContext<S>) {
37 activate(context: ActivationContext<S>) {
@@ -9,7 +9,7 let cacheId = 0;
9
9
10 const trace = TraceSource.get("@implab/core/di/ActivationContext");
10 const trace = TraceSource.get("@implab/core/di/ActivationContext");
11
11
12 function injectMethod<T, M extends keyof T, S, A>(target: T, method: M, context: ActivationContext<S>, args: A) {
12 function injectMethod<T, M extends keyof T, S extends object, A>(target: T, method: M, context: ActivationContext<S>, args: A) {
13
13
14 const m = target[method];
14 const m = target[method];
15 if (!m || typeof m !== "function")
15 if (!m || typeof m !== "function")
@@ -59,7 +59,7 export type InjectionSpec<T> = {
59 [m in keyof T]?: any;
59 [m in keyof T]?: any;
60 };
60 };
61
61
62 export interface ServiceDescriptorParams<S, T, P extends any[]> {
62 export interface ServiceDescriptorParams<S extends object, T, P extends any[]> {
63 activation?: ActivationType;
63 activation?: ActivationType;
64
64
65 owner: Container<S>;
65 owner: Container<S>;
@@ -73,7 +73,7 export interface ServiceDescriptorParams
73 cleanup?: Cleaner<T>;
73 cleanup?: Cleaner<T>;
74 }
74 }
75
75
76 export class ServiceDescriptor<S, T, P extends any[]> implements Descriptor<S, T> {
76 export class ServiceDescriptor<S extends object, T, P extends any[]> implements Descriptor<S, T> {
77 _instance: T | undefined;
77 _instance: T | undefined;
78
78
79 _hasInstance = false;
79 _hasInstance = false;
@@ -2,11 +2,11 import { ServiceDescriptor, ServiceDescr
2 import { Constructor, Factory } from "../interfaces";
2 import { Constructor, Factory } from "../interfaces";
3 import { argumentNotNull, isPrimitive } from "../safe";
3 import { argumentNotNull, isPrimitive } from "../safe";
4
4
5 export interface TypeServiceDescriptorParams<S, T extends object, P extends any[]> extends ServiceDescriptorParams<S, T, P> {
5 export interface TypeServiceDescriptorParams<S extends object, T extends object, P extends any[]> extends ServiceDescriptorParams<S, T, P> {
6 type: Constructor<T>;
6 type: Constructor<T>;
7 }
7 }
8
8
9 export class TypeServiceDescriptor<S, T extends object, P extends any[]> extends ServiceDescriptor<S, T, P> {
9 export class TypeServiceDescriptor<S extends object, T extends object, P extends any[]> extends ServiceDescriptor<S, T, P> {
10 _type: Constructor;
10 _type: Constructor;
11
11
12 constructor(opts: TypeServiceDescriptorParams<S, T, P>) {
12 constructor(opts: TypeServiceDescriptorParams<S, T, P>) {
@@ -1,21 +1,38
1 import { ActivationContext } from "./ActivationContext";
1 import { ActivationContext } from "./ActivationContext";
2
2
3 export interface Descriptor<S = any, T = any> {
3 export interface Descriptor<S extends object = any, T = any> {
4 activate(context: ActivationContext<S>): T;
4 activate(context: ActivationContext<S>): T;
5 }
5 }
6
6
7 export type ServiceMap<S> = {
7 export type ServiceMap<S extends object> = {
8 [k in keyof S]: Descriptor<S, S[k]>;
8 [k in keyof S]: Descriptor<S, S[k]>;
9 };
9 };
10
10
11 export type PartialServiceMap<S> = {
11 export type ContainerKeys<S extends object> = keyof S | keyof ContainerProvided<S>;
12
13 export type ContainerResolve<S extends object, K> =
14 K extends keyof ContainerProvided<S> ? ContainerProvided<S>[K] :
15 K extends keyof S ? S[K] : never;
16
17 export type ContainerServiceMap<S extends object> = {
18 [K in ContainerKeys<S>]: Descriptor<S, ContainerResolve<S, K>>;
19 };
20
21 export type PartialServiceMap<S extends object> = {
12 [k in keyof S]?: Descriptor<S, S[k]>;
22 [k in keyof S]?: Descriptor<S, S[k]>;
13 };
23 };
14
24
15 export interface Resolver<S> {
25 export interface Resolver<S extends object> {
16 resolve<K extends keyof ContainerServices<S>, T extends ContainerServices<S>[K] = ContainerServices<S>[K]>(name: K, def?: T): T;
26 resolve<K extends ContainerKeys<S>>(name: K, def?: ContainerResolve<S, K>): ContainerResolve<S, K>;
27 }
28
29 export interface ContainerProvided<S extends object> {
30 container: Resolver<S>;
17 }
31 }
18 export type ContainerServices<S> = S & {
32
19 container: Resolver<S>;
33 export type ContainerRegistered<S extends object> = /*{
20 };
34 [K in Exclude<keyof S, keyof ContainerProvided<S>>]: S[K];
35 };*/
36 Exclude<S, ContainerProvided<S>>;
37
21 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
38 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
@@ -4,4 +4,4 import { Descriptor } from "./interfaces
4 export function isDescriptor(x: any): x is Descriptor {
4 export function isDescriptor(x: any): x is Descriptor {
5 return (!isPrimitive(x)) &&
5 return (!isPrimitive(x)) &&
6 (x.activate instanceof Function);
6 (x.activate instanceof Function);
7 }
7 } No newline at end of file
@@ -2,5 +2,5 import { config } from "./services";
2
2
3 config()
3 config()
4 .register("bar", import("./Bar"))
4 .register("bar", import("./Bar"))
5 .register("box", import("./Box"))
5 .register("box", import("./Box"), "service");
6 .register("foo", import("./Foo"), "Foo");
6 //.register("foo", import("./Foo"), "Foo");
@@ -6,10 +6,17 import { ValueDescriptor } from "../di/V
6 import { Foo } from "../mock/Foo";
6 import { Foo } from "../mock/Foo";
7 import { Bar } from "../mock/Bar";
7 import { Bar } from "../mock/Bar";
8 import { isNull } from "../safe";
8 import { isNull } from "../safe";
9 import { Descriptor } from "../di/interfaces";
9 import { Box } from "ts/mock/Box";
10
10
11 test("Container register/resolve tests", async t => {
11 test("Container register/resolve tests", async t => {
12 const container = new Container();
12 const container = new Container<{
13 "bla-bla": string;
14 "connection": string;
15 "dbParams": {
16 timeout: number;
17 connection: string;
18 }
19 }>();
13
20
14 const connection1 = "db://localhost";
21 const connection1 = "db://localhost";
15
22
@@ -42,7 +49,11 test("Container register/resolve tests",
42
49
43 test("Container configure/resolve tests", async t => {
50 test("Container configure/resolve tests", async t => {
44
51
45 const container = new Container();
52 const container = new Container<{
53 foo: Foo;
54 box: Bar;
55 bar: Bar;
56 }>();
46
57
47 await container.configure({
58 await container.configure({
48 foo: {
59 foo: {
General Comments 0
You need to be logged in to leave comments. Login now