| @@ -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 | } | |||
| @@ -28,9 +28,6 export interface RegistrationWithService | |||||
| 28 | } |
|
28 | } | |
| 29 |
|
29 | |||
| 30 | export interface ServiceRegistration extends RegistrationWithServices { |
|
30 | export interface ServiceRegistration extends RegistrationWithServices { | |
| 31 | $type?: string | Constructor; |
|
|||
| 32 |
|
||||
| 33 | $factory?: string | Factory; |
|
|||
| 34 |
|
31 | |||
| 35 | activation?: "singleton" | "container" | "hierarchy" | "context" | "call"; |
|
32 | activation?: "singleton" | "container" | "hierarchy" | "context" | "call"; | |
| 36 |
|
33 | |||
| @@ -38,7 +35,15 export interface ServiceRegistration ext | |||||
| 38 |
|
35 | |||
| 39 | inject?: object | object[]; |
|
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 | export interface ValueRegistration { |
|
49 | export interface ValueRegistration { | |
| @@ -53,7 +58,11 export interface DependencyRegistration | |||||
| 53 | default?; |
|
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 | return (!isPrimitive(x)) && ("$type" in x || "$factory" in x); |
|
66 | return (!isPrimitive(x)) && ("$type" in x || "$factory" in x); | |
| 58 | } |
|
67 | } | |
| 59 |
|
68 | |||
General Comments 0
You need to be logged in to leave comments.
Login now
