##// END OF EJS Templates
separating configuration logic from Container
cin -
r43:477f9b6ba67f di-typescript
parent child
Show More
@@ -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 isServiceRegistration(x): x is ServiceRegistration {
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