| @@ -0,0 +1,142 | |||
|
|
1 | import { ServiceRegistration, TypeRegistration, FactoryRegistration, ServiceMap, Descriptor, isDescriptor, isDependencyRegistration, DependencyRegistration, ValueRegistration, ActivationType, isValueRegistration, isTypeRegistration, isFactoryRegistration } from "./interfaces"; | |
|
|
2 | import { isNullOrEmptyString, argumentNotEmptyString, isPrimitive } from "../safe"; | |
|
|
3 | import { AggregateDescriptor } from "./AggregateDescriptor"; | |
|
|
4 | import { ValueDescriptor } from "./ValueDescriptor"; | |
|
|
5 | import { ServiceDescriptorParams } from "./ServiceDescriptor"; | |
|
|
6 | import { Container } from "./Container"; | |
|
|
7 | import { Constructor } from "../interfaces"; | |
|
|
8 | ||
|
|
9 | interface MapOf<T> { | |
|
|
10 | [key: string]: T; | |
|
|
11 | } | |
|
|
12 | ||
|
|
13 | type _key = string | number; | |
|
|
14 | ||
|
|
15 | export class Configuration { | |
|
|
16 | ||
|
|
17 | _hasInnerDescriptors = false; | |
|
|
18 | ||
|
|
19 | _container: Container; | |
|
|
20 | ||
|
|
21 | _path: Array<_key>; | |
|
|
22 | ||
|
|
23 | async _visitRegistrations(data, name: _key) { | |
|
|
24 | this._path.push(name); | |
|
|
25 | ||
|
|
26 | if (data.constructor && | |
|
|
27 | data.constructor.prototype !== Object.prototype) | |
|
|
28 | throw new Error("Configuration must be a simple object"); | |
|
|
29 | ||
|
|
30 | const o: ServiceMap = {}; | |
|
|
31 | const keys = Object.keys(data); | |
|
|
32 | ||
|
|
33 | const res = await Promise.all(keys.map(k => this._visit(data[k], k))); | |
|
|
34 | keys.forEach((k, i) => { | |
|
|
35 | o[k] = isDescriptor(res[i]) ? res[i] : new AggregateDescriptor(res[i]); | |
|
|
36 | }); | |
|
|
37 | ||
|
|
38 | this._path.pop(); | |
|
|
39 | ||
|
|
40 | return o; | |
|
|
41 | } | |
|
|
42 | ||
|
|
43 | async _visit(data, name: string): Promise<any> { | |
|
|
44 | if (isPrimitive(data) || isDescriptor(data)) | |
|
|
45 | return data; | |
|
|
46 | ||
|
|
47 | if (isDependencyRegistration(data)) { | |
|
|
48 | return this._visitDependencyRegistration(data, name); | |
|
|
49 | } else if (isValueRegistration(data)) { | |
|
|
50 | return this._visitValueRegistration(data, name); | |
|
|
51 | } else if (isTypeRegistration(data)) { | |
|
|
52 | return this._visitTypeRegistration(data, name); | |
|
|
53 | } else if (isFactoryRegistration(data)) { | |
|
|
54 | return this._visitFactoryRegistration(data, name); | |
|
|
55 | } else if (data instanceof Array) { | |
|
|
56 | return this._visitArray(data, name); | |
|
|
57 | } | |
|
|
58 | ||
|
|
59 | return this._visitObject(data, name); | |
|
|
60 | } | |
|
|
61 | ||
|
|
62 | async _resolveType(moduleName: string, typeName: string): Promise<Constructor> { | |
|
|
63 | ||
|
|
64 | } | |
|
|
65 | ||
|
|
66 | async _visitObject(data: object, name: _key): Promise<object> { | |
|
|
67 | this._path.push(name); | |
|
|
68 | this._path.pop(); | |
|
|
69 | } | |
|
|
70 | ||
|
|
71 | async _visitArray(data: any[], name: _key): Promise<any[]> { | |
|
|
72 | this._path.push(name); | |
|
|
73 | this._path.pop(); | |
|
|
74 | } | |
|
|
75 | ||
|
|
76 | async _makeServiceParams(data: ServiceRegistration) { | |
|
|
77 | const opts: any = {}; | |
|
|
78 | if (data.services) | |
|
|
79 | opts.services = await this._visitRegistrations(data.services, "services"); | |
|
|
80 | ||
|
|
81 | if (data.inject) { | |
|
|
82 | if (data.inject instanceof Array) { | |
|
|
83 | this._path.push("inject"); | |
|
|
84 | opts.inject = Promise.all(data.inject.map((x, i) => this._visitObject(x, i))); | |
|
|
85 | this._path.pop(); | |
|
|
86 | } else { | |
|
|
87 | opts.inject = [this._visitObject(data.inject, "inject")]; | |
|
|
88 | } | |
|
|
89 | } | |
|
|
90 | ||
|
|
91 | if (data.params) | |
|
|
92 | opts.params = await this._visit(data.params, "params"); | |
|
|
93 | ||
|
|
94 | if (data.activation) { | |
|
|
95 | if (typeof (data.activation) === "string") { | |
|
|
96 | switch (data.activation.toLowerCase()) { | |
|
|
97 | case "singleton": | |
|
|
98 | opts.activation = ActivationType.Singleton; | |
|
|
99 | break; | |
|
|
100 | case "container": | |
|
|
101 | opts.activation = ActivationType.Container; | |
|
|
102 | break; | |
|
|
103 | case "hierarchy": | |
|
|
104 | opts.activation = ActivationType.Hierarchy; | |
|
|
105 | break; | |
|
|
106 | case "context": | |
|
|
107 | opts.activation = ActivationType.Context; | |
|
|
108 | break; | |
|
|
109 | case "call": | |
|
|
110 | opts.activation = ActivationType.Call; | |
|
|
111 | break; | |
|
|
112 | default: | |
|
|
113 | throw new Error("Unknown activation type: " + | |
|
|
114 | data.activation); | |
|
|
115 | } | |
|
|
116 | } else { | |
|
|
117 | opts.activation = Number(data.activation); | |
|
|
118 | } | |
|
|
119 | } | |
|
|
120 | ||
|
|
121 | if (data.cleanup) | |
|
|
122 | opts.cleanup = data.cleanup; | |
|
|
123 | } | |
|
|
124 | ||
|
|
125 | async _visitValueRegistration(item: ValueRegistration, name: _key) { | |
|
|
126 | this._path.push(name); | |
|
|
127 | this._path.pop(); | |
|
|
128 | } | |
|
|
129 | ||
|
|
130 | async _visitDependencyRegistration(item: DependencyRegistration, name: _key) { | |
|
|
131 | this._path.push(name); | |
|
|
132 | this._path.pop(); | |
|
|
133 | } | |
|
|
134 | ||
|
|
135 | async _visitTypeRegistration(item: TypeRegistration, name: _key) { | |
|
|
136 | argumentNotEmptyString(item.$type, "item.$type"); | |
|
|
137 | } | |
|
|
138 | ||
|
|
139 | async _visitFactoryRegistration(item: FactoryRegistration, name: _key) { | |
|
|
140 | argumentNotEmptyString(item.$factory, "item.$type"); | |
|
|
141 | } | |
|
|
142 | } | |
| @@ -1,66 +1,75 | |||
|
|
1 | 1 | import { isNull, isPrimitive } from "../safe"; |
|
|
2 | 2 | import { ActivationContext } from "./ActivationContext"; |
|
|
3 | 3 | import { Constructor, Factory } from "../interfaces"; |
|
|
4 | 4 | |
|
|
5 | 5 | export interface Descriptor { |
|
|
6 | 6 | activate(context: ActivationContext, name?: string); |
|
|
7 | 7 | } |
|
|
8 | 8 | |
|
|
9 | 9 | export function isDescriptor(x): x is Descriptor { |
|
|
10 | 10 | return (!isPrimitive(x)) && |
|
|
11 | 11 | (x.activate instanceof Function); |
|
|
12 | 12 | } |
|
|
13 | 13 | |
|
|
14 | 14 | export interface ServiceMap { |
|
|
15 | 15 | [s: string]: Descriptor; |
|
|
16 | 16 | } |
|
|
17 | 17 | |
|
|
18 | 18 | export enum ActivationType { |
|
|
19 | 19 | Singleton, |
|
|
20 | 20 | Container, |
|
|
21 | 21 | Hierarchy, |
|
|
22 | 22 | Context, |
|
|
23 | 23 | Call |
|
|
24 | 24 | } |
|
|
25 | 25 | |
|
|
26 | 26 | export interface RegistrationWithServices { |
|
|
27 | 27 | services?: object; |
|
|
28 | 28 | } |
|
|
29 | 29 | |
|
|
30 | 30 | export interface ServiceRegistration extends RegistrationWithServices { |
|
|
31 | $type?: string | Constructor; | |
|
|
32 | ||
|
|
33 | $factory?: string | Factory; | |
|
|
34 | 31 | |
|
|
35 | 32 | activation?: "singleton" | "container" | "hierarchy" | "context" | "call"; |
|
|
36 | 33 | |
|
|
37 | 34 | params?; |
|
|
38 | 35 | |
|
|
39 | 36 | inject?: object | object[]; |
|
|
40 | 37 | |
|
|
41 | cleanup: (instance) => void | string; | |
|
|
38 | cleanup?: (instance) => void | string; | |
|
|
39 | } | |
|
|
40 | ||
|
|
41 | export interface TypeRegistration extends ServiceRegistration { | |
|
|
42 | $type: string | Constructor; | |
|
|
43 | } | |
|
|
44 | ||
|
|
45 | export interface FactoryRegistration extends ServiceRegistration { | |
|
|
46 | $factory: string | Factory; | |
|
|
42 | 47 | } |
|
|
43 | 48 | |
|
|
44 | 49 | export interface ValueRegistration { |
|
|
45 | 50 | $value; |
|
|
46 | 51 | parse?: boolean; |
|
|
47 | 52 | } |
|
|
48 | 53 | |
|
|
49 | 54 | export interface DependencyRegistration extends RegistrationWithServices { |
|
|
50 | 55 | $dependency: string; |
|
|
51 | 56 | lazy?: boolean; |
|
|
52 | 57 | optional?: boolean; |
|
|
53 | 58 | default?; |
|
|
54 | 59 | } |
|
|
55 | 60 | |
|
|
56 |
export function is |
|
|
|
61 | export function isTypeRegistration(x): x is TypeRegistration { | |
|
|
62 | return (!isPrimitive(x)) && ("$type" in x || "$factory" in x); | |
|
|
63 | } | |
|
|
64 | ||
|
|
65 | export function isFactoryRegistration(x): x is FactoryRegistration { | |
|
|
57 | 66 | return (!isPrimitive(x)) && ("$type" in x || "$factory" in x); |
|
|
58 | 67 | } |
|
|
59 | 68 | |
|
|
60 | 69 | export function isValueRegistration(x): x is ValueRegistration { |
|
|
61 | 70 | return (!isPrimitive(x)) && ("$value" in x); |
|
|
62 | 71 | } |
|
|
63 | 72 | |
|
|
64 | 73 | export function isDependencyRegistration(x): x is DependencyRegistration { |
|
|
65 | 74 | return (!isPrimitive(x)) && ("$dependency" in x); |
|
|
66 | 75 | } |
General Comments 0
You need to be logged in to leave comments.
Login now
