| @@ -0,0 +1,84 | |||||
|
|
1 | import { argumentNotEmptyString, each } from "../safe"; | |||
|
|
2 | import { ActivationContext } from "./ActivationContext"; | |||
|
|
3 | import { Descriptor, PartialServiceMap, ContainerResolve, ContainerKeys } from "./interfaces"; | |||
|
|
4 | import { ActivationError } from "./ActivationError"; | |||
|
|
5 | ||||
|
|
6 | export interface ReferenceDescriptorParams<S extends object, K extends ContainerKeys<S>> { | |||
|
|
7 | name: K; | |||
|
|
8 | optional?: boolean; | |||
|
|
9 | default?: ContainerResolve<S, K>; | |||
|
|
10 | services?: PartialServiceMap<S>; | |||
|
|
11 | } | |||
|
|
12 | ||||
|
|
13 | export class LazyReferenceDescriptor<S extends object = any, K extends ContainerKeys<S> = ContainerKeys<S>> | |||
|
|
14 | implements Descriptor<S, ((args?: PartialServiceMap<S>) => ContainerResolve<S, K>)> { | |||
|
|
15 | ||||
|
|
16 | _name: K; | |||
|
|
17 | ||||
|
|
18 | _optional = false; | |||
|
|
19 | ||||
|
|
20 | _default: ContainerResolve<S, K> | undefined; | |||
|
|
21 | ||||
|
|
22 | _services: PartialServiceMap<S>; | |||
|
|
23 | ||||
|
|
24 | constructor(opts: ReferenceDescriptorParams<S, K>) { | |||
|
|
25 | argumentNotEmptyString(opts && opts.name, "opts.name"); | |||
|
|
26 | this._name = opts.name; | |||
|
|
27 | this._optional = !!opts.optional; | |||
|
|
28 | this._default = opts.default; | |||
|
|
29 | ||||
|
|
30 | this._services = (opts.services || {}) as PartialServiceMap<S>; | |||
|
|
31 | } | |||
|
|
32 | ||||
|
|
33 | activate(context: ActivationContext<S>) { | |||
|
|
34 | // добавляем сервисы | |||
|
|
35 | if (this._services) { | |||
|
|
36 | each(this._services, (v, k) => context.register(k, v)); | |||
|
|
37 | } | |||
|
|
38 | ||||
|
|
39 | const saved = context.clone(); | |||
|
|
40 | ||||
|
|
41 | return (cfg?: PartialServiceMap<S>) => { | |||
|
|
42 | // защищаем контекст на случай исключения в процессе | |||
|
|
43 | // активации | |||
|
|
44 | const ct = saved.clone(); | |||
|
|
45 | try { | |||
|
|
46 | if (cfg) { | |||
|
|
47 | each(cfg, (v, k) => ct.register(k, v)); | |||
|
|
48 | } | |||
|
|
49 | ||||
|
|
50 | return this._optional ? ct.resolve(this._name, this._default) : ct | |||
|
|
51 | .resolve(this._name); | |||
|
|
52 | } catch (error) { | |||
|
|
53 | throw new ActivationError(this._name.toString(), ct.getStack(), error); | |||
|
|
54 | } | |||
|
|
55 | }; | |||
|
|
56 | ||||
|
|
57 | } | |||
|
|
58 | ||||
|
|
59 | toString() { | |||
|
|
60 | const opts = []; | |||
|
|
61 | if (this._optional) | |||
|
|
62 | opts.push("optional"); | |||
|
|
63 | ||||
|
|
64 | opts.push("lazy"); | |||
|
|
65 | ||||
|
|
66 | const parts = [ | |||
|
|
67 | "@ref " | |||
|
|
68 | ]; | |||
|
|
69 | if (opts.length) { | |||
|
|
70 | parts.push("{"); | |||
|
|
71 | parts.push(opts.join()); | |||
|
|
72 | parts.push("} "); | |||
|
|
73 | } | |||
|
|
74 | ||||
|
|
75 | parts.push(this._name.toString()); | |||
|
|
76 | ||||
|
|
77 | if (this._default !== undefined && this._default !== null) { | |||
|
|
78 | parts.push(" = "); | |||
|
|
79 | parts.push(String(this._default)); | |||
|
|
80 | } | |||
|
|
81 | ||||
|
|
82 | return parts.join(""); | |||
|
|
83 | } | |||
|
|
84 | } | |||
| @@ -72,6 +72,8 type ServiceModule<T, S extends object, | |||||
| 72 | [m in M]: Builder<T, S>; |
|
72 | [m in M]: Builder<T, S>; | |
| 73 | }; |
|
73 | }; | |
| 74 |
|
74 | |||
|
|
75 | type PromiseOrValue<T> = PromiseLike<T> | T; | |||
|
|
76 | ||||
| 75 | export interface Config<S extends object, Y extends keyof S = keyof S> { |
|
77 | export interface Config<S extends object, Y extends keyof S = keyof S> { | |
| 76 | register<K extends Y>(name: K, builder: Builder<S[K], S>): Config<S, Exclude<Y, K>>; |
|
78 | register<K extends Y>(name: K, builder: Builder<S[K], S>): Config<S, Exclude<Y, K>>; | |
| 77 | register<K extends Y>(name: K, m: Promise<ServiceModule<S[K], S>>): Config<S, Exclude<Y, K>>; |
|
79 | register<K extends Y>(name: K, m: Promise<ServiceModule<S[K], S>>): Config<S, Exclude<Y, K>>; | |
| @@ -18,6 +18,7 import { Cancellation } from "../Cancell | |||||
| 18 | import { makeResolver } from "./ResolverHelper"; |
|
18 | import { makeResolver } from "./ResolverHelper"; | |
| 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 |
|
22 | |||
| 22 | export interface RegistrationScope<S extends object> { |
|
23 | export interface RegistrationScope<S extends object> { | |
| 23 |
|
24 | |||
| @@ -357,13 +358,13 export class Configuration<S extends obj | |||||
| 357 | async _visitDependencyRegistration<K extends keyof S>(data: DependencyRegistration<S, K>, name: string) { |
|
358 | async _visitDependencyRegistration<K extends keyof S>(data: DependencyRegistration<S, K>, name: string) { | |
| 358 | argumentNotEmptyString(data && data.$dependency, "data.$dependency"); |
|
359 | argumentNotEmptyString(data && data.$dependency, "data.$dependency"); | |
| 359 | this._enter(name); |
|
360 | this._enter(name); | |
| 360 | const d = new ReferenceDescriptor<S, K>({ |
|
361 | const options = { | |
| 361 | name: data.$dependency, |
|
362 | name: data.$dependency, | |
| 362 | lazy: data.lazy, |
|
|||
| 363 | optional: data.optional, |
|
363 | optional: data.optional, | |
| 364 | default: data.default, |
|
364 | default: data.default, | |
| 365 | services: data.services && await this._visitRegistrations(data.services, "services") |
|
365 | services: data.services && await this._visitRegistrations(data.services, "services") | |
| 366 |
} |
|
366 | }; | |
|
|
367 | const d = data.lazy ? new LazyReferenceDescriptor<S, K>(options) : new ReferenceDescriptor<S, K>(options); | |||
| 367 | this._leave(); |
|
368 | this._leave(); | |
| 368 | return d; |
|
369 | return d; | |
| 369 | } |
|
370 | } | |
| @@ -1,23 +1,19 | |||||
| 1 | import { argumentNotEmptyString, each } from "../safe"; |
|
1 | import { argumentNotEmptyString, each } from "../safe"; | |
| 2 | import { ActivationContext } from "./ActivationContext"; |
|
2 | import { ActivationContext } from "./ActivationContext"; | |
| 3 | import { Descriptor, PartialServiceMap, ContainerResolve, ContainerKeys } from "./interfaces"; |
|
3 | import { Descriptor, PartialServiceMap, ContainerResolve, ContainerKeys } from "./interfaces"; | |
| 4 | import { ActivationError } from "./ActivationError"; |
|
|||
| 5 |
|
4 | |||
| 6 | export interface ReferenceDescriptorParams<S extends object, K extends ContainerKeys<S>> { |
|
5 | export interface ReferenceDescriptorParams<S extends object, K extends ContainerKeys<S>> { | |
| 7 | name: K; |
|
6 | name: K; | |
| 8 | lazy?: boolean; |
|
|||
| 9 | optional?: boolean; |
|
7 | optional?: boolean; | |
| 10 | default?: ContainerResolve<S, K>; |
|
8 | default?: ContainerResolve<S, K>; | |
| 11 | services?: PartialServiceMap<S>; |
|
9 | services?: PartialServiceMap<S>; | |
| 12 | } |
|
10 | } | |
| 13 |
|
11 | |||
| 14 | export class ReferenceDescriptor<S extends object = any, K extends ContainerKeys<S> = ContainerKeys<S>> |
|
12 | export class ReferenceDescriptor<S extends object = any, K extends ContainerKeys<S> = ContainerKeys<S>> | |
| 15 |
implements Descriptor<S, ContainerResolve<S, K> |
|
13 | implements Descriptor<S, ContainerResolve<S, K>> { | |
| 16 |
|
14 | |||
| 17 | _name: K; |
|
15 | _name: K; | |
| 18 |
|
16 | |||
| 19 | _lazy = false; |
|
|||
| 20 |
|
||||
| 21 | _optional = false; |
|
17 | _optional = false; | |
| 22 |
|
18 | |||
| 23 | _default: ContainerResolve<S, K> | undefined; |
|
19 | _default: ContainerResolve<S, K> | undefined; | |
| @@ -27,7 +23,6 export class ReferenceDescriptor<S exten | |||||
| 27 | constructor(opts: ReferenceDescriptorParams<S, K>) { |
|
23 | constructor(opts: ReferenceDescriptorParams<S, K>) { | |
| 28 | argumentNotEmptyString(opts && opts.name, "opts.name"); |
|
24 | argumentNotEmptyString(opts && opts.name, "opts.name"); | |
| 29 | this._name = opts.name; |
|
25 | this._name = opts.name; | |
| 30 | this._lazy = !!opts.lazy; |
|
|||
| 31 | this._optional = !!opts.optional; |
|
26 | this._optional = !!opts.optional; | |
| 32 | this._default = opts.default; |
|
27 | this._default = opts.default; | |
| 33 |
|
28 | |||
| @@ -40,39 +35,17 export class ReferenceDescriptor<S exten | |||||
| 40 | each(this._services, (v, k) => context.register(k, v)); |
|
35 | each(this._services, (v, k) => context.register(k, v)); | |
| 41 | } |
|
36 | } | |
| 42 |
|
37 | |||
| 43 | if (this._lazy) { |
|
38 | const res = this._optional ? | |
| 44 | const saved = context.clone(); |
|
|||
| 45 |
|
||||
| 46 | return (cfg?: PartialServiceMap<S>) => { |
|
|||
| 47 | // защищаем контекст на случай исключения в процессе |
|
|||
| 48 | // активации |
|
|||
| 49 | const ct = saved.clone(); |
|
|||
| 50 | try { |
|
|||
| 51 | if (cfg) { |
|
|||
| 52 | each(cfg, (v, k) => ct.register(k, v)); |
|
|||
| 53 | } |
|
|||
| 54 |
|
||||
| 55 | return this._optional ? ct.resolve(this._name, this._default) : ct |
|
|||
| 56 | .resolve(this._name); |
|
|||
| 57 | } catch (error) { |
|
|||
| 58 | throw new ActivationError(this._name.toString(), ct.getStack(), error); |
|
|||
| 59 | } |
|
|||
| 60 | }; |
|
|||
| 61 | } else { |
|
|||
| 62 | const v = this._optional ? |
|
|||
| 63 |
|
|
39 | context.resolve(this._name, this._default) : | |
| 64 |
|
|
40 | context.resolve(this._name); | |
| 65 |
|
41 | |||
| 66 |
|
|
42 | return res; | |
| 67 | } |
|
|||
| 68 | } |
|
43 | } | |
| 69 |
|
44 | |||
| 70 | toString() { |
|
45 | toString() { | |
| 71 | const opts = []; |
|
46 | const opts = []; | |
| 72 | if (this._optional) |
|
47 | if (this._optional) | |
| 73 | opts.push("optional"); |
|
48 | opts.push("optional"); | |
| 74 | if (this._lazy) |
|
|||
| 75 | opts.push("lazy"); |
|
|||
| 76 |
|
49 | |||
| 77 | const parts = [ |
|
50 | const parts = [ | |
| 78 | "@ref " |
|
51 | "@ref " | |
General Comments 0
You need to be logged in to leave comments.
Login now
