##// END OF EJS Templates
tests
cin -
r41:eae7e609c38a di-typescript
parent child
Show More
@@ -0,0 +1,3
1 export class Bar {
2 name = "bar";
3 }
@@ -0,0 +1,3
1 export class Foo {
2 name = "foo";
3 }
@@ -1,4 +1,4
1 Copyright 2017-2018 Implab team
1 Copyright 2017-2019 Implab team
2 2
3 3 Redistribution and use in source and binary forms, with or without
4 4 modification, are permitted provided that the following conditions are met:
@@ -83,7 +83,7
83 83 },
84 84 "duplexer": {
85 85 "version": "0.1.1",
86 "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
86 "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
87 87 "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
88 88 "dev": true
89 89 },
@@ -128,7 +128,7
128 128 "dependencies": {
129 129 "tape": {
130 130 "version": "2.3.3",
131 "resolved": "http://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
131 "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
132 132 "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
133 133 "dev": true,
134 134 "requires": {
@@ -288,7 +288,7
288 288 },
289 289 "path-is-absolute": {
290 290 "version": "1.0.1",
291 "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
291 "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
292 292 "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
293 293 "dev": true
294 294 },
@@ -300,7 +300,7
300 300 },
301 301 "readable-stream": {
302 302 "version": "1.1.14",
303 "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
303 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
304 304 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
305 305 "dev": true,
306 306 "requires": {
@@ -353,7 +353,7
353 353 },
354 354 "string_decoder": {
355 355 "version": "0.10.31",
356 "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
356 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
357 357 "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
358 358 "dev": true
359 359 },
@@ -410,13 +410,13
410 410 },
411 411 "through": {
412 412 "version": "2.3.8",
413 "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
413 "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
414 414 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
415 415 "dev": true
416 416 },
417 417 "through2": {
418 418 "version": "0.2.3",
419 "resolved": "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
419 "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
420 420 "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
421 421 "dev": true,
422 422 "requires": {
@@ -8,7 +8,7 const trace = TraceSource.get("@implab/c
8 8 export interface ActivationContextInfo {
9 9 name: string;
10 10
11 service: Descriptor;
11 service: string;
12 12
13 13 scope: ServiceMap;
14 14 }
@@ -22,12 +22,17 export class ActivationContext {
22 22
23 23 _visited: object;
24 24
25 _name: string;
26
27 _localized: boolean;
28
25 29 container: Container;
26 30
27 constructor(container: Container, services: ServiceMap, cache?: object, visited?) {
31 constructor(container: Container, services: ServiceMap, name?: string, cache?: object, visited?) {
28 32 argumentNotNull(container, "container");
29 33 argumentNotNull(services, "services");
30 34
35 this._name = name;
31 36 this._visited = visited || {};
32 37 this._stack = [];
33 38 this._cache = cache || {};
@@ -35,7 +40,11 export class ActivationContext {
35 40 this.container = container;
36 41 }
37 42
38 getService(name, def?): any {
43 getName() {
44 return this._name;
45 }
46
47 resolve(name, def?): any {
39 48 const d = this._services[name];
40 49
41 50 if (!d)
@@ -44,7 +53,7 export class ActivationContext {
44 53 else
45 54 throw new Error(`Service ${name} not found`);
46 55
47 return isDescriptor(d) ? d.activate(this, name) : d;
56 return this.activate(d, name);
48 57 }
49 58
50 59 /**
@@ -62,7 +71,8 export class ActivationContext {
62 71 clone() {
63 72 return new ActivationContext(
64 73 this.container,
65 Object.create(this._services),
74 this._services,
75 this._name,
66 76 this._cache,
67 77 this._visited
68 78 );
@@ -80,25 +90,18 export class ActivationContext {
80 90 return (this._cache[id] = value);
81 91 }
82 92
83 parse(data, name: string) {
84 if (isPrimitive(data))
85 return data;
93 activate(d: Descriptor, name: string) {
94 if (trace.isLogEnabled())
95 trace.log(`enter ${name} ${d}`);
86 96
87 if (isDescriptor(data)) {
88 return data.activate(this, name);
89 } else if (data instanceof Array) {
90 this.enter(name);
91 const v = data.map( (x, i) => this.parse(x, `[${i}]`));
97 this.enter(name, d.toString());
98 const v = d.activate(this);
92 99 this.leave();
100
101 if (trace.isLogEnabled())
102 trace.log(`leave ${name}`);
103
93 104 return v;
94 } else {
95 this.enter(name);
96 const result = {};
97 for (const p in data)
98 result[p] = this.parse(data[p], "." + p);
99 this.leave();
100 return result;
101 }
102 105 }
103 106
104 107 visit(id: string) {
@@ -111,24 +114,19 export class ActivationContext {
111 114 return this._stack.slice().reverse();
112 115 }
113 116
114 enter(name: string, d?: Descriptor, localize?: boolean) {
115 if (trace.isLogEnabled())
116 trace.log("enter " + name + " " + (d || "") +
117 (localize ? " localize" : ""));
117 private enter(name: string, service: string) {
118 118 this._stack.push({
119 119 name,
120 service: d,
120 service,
121 121 scope: this._services
122 122 });
123 if (localize)
123 this._name = name;
124 124 this._services = Object.create(this._services);
125 125 }
126 126
127 leave() {
127 private leave() {
128 128 const ctx = this._stack.pop();
129 129 this._services = ctx.scope;
130
131 if (trace.isLogEnabled())
132 trace.log("leave " + ctx.name + " " + (ctx.service || ""));
130 this._name = ctx.name;
133 131 }
134 132 }
@@ -27,7 +27,7 export class ActivationError {
27 27 if (this.activationStack) {
28 28 parts.push("at");
29 29 this.activationStack
30 .forEach(x => parts.push(` ${x.name} ${x.service ? x.service.toString() : ""}`));
30 .forEach(x => parts.push(` ${x.name} ${x.service}`));
31 31
32 32 }
33 33
@@ -1,5 +1,6
1 import { Descriptor } from "./interfaces";
1 import { Descriptor, isDescriptor } from "./interfaces";
2 2 import { ActivationContext } from "./ActivationContext";
3 import { isPrimitive } from "util";
3 4
4 5 export class AggregateDescriptor implements Descriptor {
5 6 _value: object;
@@ -8,17 +9,29 export class AggregateDescriptor impleme
8 9 this._value = value;
9 10 }
10 11
11 activate(context: ActivationContext, name: string) {
12 context.enter(name);
13 const v = context.parse(this._value, ".params");
14 context.leave();
15 return v;
12 activate(context: ActivationContext) {
13 return this._parse(this._value, context, "$value");
16 14 }
17 15
18 isInstanceCreated(): boolean {
19 return false;
16 // TODO: make async
17 _parse(value, context: ActivationContext, path: string) {
18 if (isPrimitive(value))
19 return value;
20
21 if (isDescriptor(value))
22 return context.activate(value, path);
23
24 if (value instanceof Array)
25 return value.map((x, i) => this._parse(x, context, `${path}[${i}]`));
26
27 const t = {};
28 for (const p of Object.keys(value))
29 t[p] = this._parse(value[p], context, `${path}.${p}`);
30 return t;
31
20 32 }
21 getInstance(): any {
22 throw new Error("Not supported");
33
34 toString() {
35 return "@walk";
23 36 }
24 37 }
@@ -1,13 +1,14
1 1 import { ActivationContext } from "./ActivationContext";
2 2 import { ValueDescriptor } from "./ValueDescriptor";
3 3 import { ActivationError } from "./ActivationError";
4 import { isDescriptor, ActivationType, ServiceMap, isDependencyRegistration, isValueRegistration, ServiceRegistration } from "./interfaces";
4 import { isDescriptor, ActivationType, ServiceMap, isDependencyRegistration, isValueRegistration, ServiceRegistration, DependencyRegistration } from "./interfaces";
5 5 import { AggregateDescriptor } from "./AggregateDescriptor";
6 import { isPrimitive } from "../safe";
6 import { isPrimitive, pmap } from "../safe";
7 7 import { ReferenceDescriptor } from "./ReferenceDescriptor";
8 8 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
9 9 import { ModuleResolverBase } from "./ModuleResolverBase";
10 10 import format = require("../text/format");
11 import { throws } from "assert";
11 12
12 13 export class Container {
13 14 _services: ServiceMap;
@@ -39,35 +40,36 export class Container {
39 40 return this._parent;
40 41 }
41 42
42 getService(name: string, def?) {
43 resolve(name: string, def?) {
43 44 const d = this._services[name];
44 if (!d)
45 if (d === undefined) {
45 46 if (arguments.length > 1)
46 47 return def;
47 48 else
48 49 throw new Error("Service '" + name + "' isn't found");
49
50 if (!isDescriptor(d))
51 return d;
52
53 if (d.isInstanceCreated())
54 return d.getInstance();
50 }
55 51
56 52 const context = new ActivationContext(this, this._services);
57
58 53 try {
59 return d.activate(context, name);
54 return context.activate(d, name);
60 55 } catch (error) {
61 56 throw new ActivationError(name, context.getStack(), error);
62 57 }
63 58 }
64 59
60 getService(name: string, def?) {
61 return this.resolve.apply(this, arguments);
62 }
63
65 64 register(nameOrCollection, service?) {
66 65 if (arguments.length === 1) {
67 66 const data = nameOrCollection;
68 67 for (const name in data)
69 68 this.register(name, data[name]);
70 69 } else {
70 if (!isDescriptor(service))
71 throw new Error("The service parameter must be a descriptor");
72
71 73 this._services[nameOrCollection] = service;
72 74 }
73 75 return this;
@@ -126,19 +128,7 export class Container {
126 128 async _configure(data: object, opts?: { resolver: ModuleResolverBase }) {
127 129 const resolver = (opts && opts.resolver) || this._resolver;
128 130
129 const services: ServiceMap = {};
130
131 resolver.beginBatch();
132
133 async function parse(k) {
134 services[k] = await this._parse(data[k], resolver);
135 }
136
137 const batch = Object.keys(data).map(parse);
138
139 resolver.completeBatch();
140
141 await Promise.all(batch);
131 const services = await this._parseRegistrations(data, resolver);
142 132
143 133 this.register(services);
144 134 }
@@ -148,17 +138,8 export class Container {
148 138 return registration;
149 139
150 140 if (isDependencyRegistration(registration)) {
151
152 return new ReferenceDescriptor({
153 name: registration.$dependency,
154 lazy: registration.lazy,
155 optional: registration.optional,
156 default: registration.default,
157 services: registration.services && this._parseObject(registration.services, resolver)
158 });
159
141 return this._paseReference(registration, resolver);
160 142 } else if (isValueRegistration(registration)) {
161
162 143 return !registration.parse ?
163 144 new ValueDescriptor(registration.$value) :
164 145 new AggregateDescriptor(this._parse(registration.$value, resolver));
@@ -172,6 +153,16 export class Container {
172 153 return this._parseObject(registration, resolver);
173 154 }
174 155
156 async _paseReference(registration: DependencyRegistration, resolver: ModuleResolverBase) {
157 return new ReferenceDescriptor({
158 name: registration.$dependency,
159 lazy: registration.lazy,
160 optional: registration.optional,
161 default: registration.default,
162 services: registration.services && await this._parseRegistrations(registration.services, resolver)
163 });
164 }
165
175 166 async _parseService(data: ServiceRegistration, resolver: ModuleResolverBase) {
176 167 const opts: ServiceDescriptorParams = {
177 168 owner: this
@@ -194,12 +185,14 export class Container {
194 185 }
195 186
196 187 if (data.services)
197 opts.services = await this._parseObject(data.services, resolver);
188 opts.services = await this._parseRegistrations(data.services, resolver);
198 189
190 if (data.inject) {
199 191 if (data.inject instanceof Array)
200 192 opts.inject = await Promise.all(data.inject.map(x => this._parseObject(x, resolver)));
201 193 else
202 194 opts.inject = [await this._parseObject(data.inject, resolver)];
195 }
203 196
204 197 if (data.params)
205 198 opts.params = this._parse(data.params, resolver);
@@ -237,7 +230,7 export class Container {
237 230 return new ServiceDescriptor(opts);
238 231 }
239 232
240 _parseObject(data: object, resolver: ModuleResolverBase) {
233 async _parseObject(data: object, resolver: ModuleResolverBase) {
241 234 if (data.constructor &&
242 235 data.constructor.prototype !== Object.prototype)
243 236 return new ValueDescriptor(data);
@@ -245,16 +238,42 export class Container {
245 238 const o = {};
246 239
247 240 for (const p in data)
248 o[p] = this._parse(data[p], resolver);
241 o[p] = await this._parse(data[p], resolver);
242
243 // TODO: handle inline descriptors properly
244 // const ex = {
245 // activate(ctx) {
246 // const value = ctx.activate(this.prop, "prop");
247 // // some code
248 // },
249
250 // // will be turned to ReferenceDescriptor
251 // prop: { $dependency: "depName" }
252 // };
249 253
250 254 return o;
251 255 }
252 256
253 _parseArray(data: Array<any>, resolver: ModuleResolverBase) {
257 async _parseArray(data: Array<any>, resolver: ModuleResolverBase) {
254 258 if (data.constructor &&
255 259 data.constructor.prototype !== Array.prototype)
256 260 return new ValueDescriptor(data);
257 261
258 return data.map(x => this._parse(x, resolver));
262 return pmap(data, x => this._parse(x, resolver));
263 }
264
265 async _parseRegistrations(data: object, resolver: ModuleResolverBase) {
266 if (data.constructor &&
267 data.constructor.prototype !== Object.prototype)
268 throw new Error("Registrations must be a simple object");
269
270 const o: ServiceMap = {};
271
272 for (const p of Object.keys(data)) {
273 const v = await this._parse(data[p], resolver);
274 o[p] = isDescriptor(v) ? v : new AggregateDescriptor(v);
275 }
276
277 return o;
259 278 }
260 279 }
@@ -27,41 +27,37 export class ReferenceDescriptor impleme
27 27 this._name = opts.name;
28 28 this._lazy = !!opts.lazy;
29 29 this._optional = !!opts.optional;
30 this._default = !!opts.default;
30 this._default = opts.default;
31 31 this._services = opts.services;
32 32 }
33 33
34 34 activate(context: ActivationContext, name: string) {
35
36 if (this._lazy) {
37 // сохраняем контекст активации
38 context = context.clone();
39
40 35 // добавляем сервисы
41 36 if (this._services) {
42 37 for (const p of Object.keys(this._services))
43 38 context.register(p, this._services[p]);
44 39 }
45 40
41 if (this._lazy) {
42 const saved = context.clone();
43
46 44 return (cfg: ServiceMap) => {
47 45 // защищаем контекст на случай исключения в процессе
48 46 // активации
49 const ct = context.clone();
47 const ct = saved.clone();
50 48 try {
51 49 if (cfg) {
52 50 for (const k in cfg)
53 51 ct.register(k, cfg[k]);
54 52 }
55 53
56 return this._optional ? ct.getService(this._name, this._default) : ct
57 .getService(this._name);
54 return this._optional ? ct.resolve(this._name, this._default) : ct
55 .resolve(this._name);
58 56 } catch (error) {
59 57 throw new ActivationError(this._name, ct.getStack(), error);
60 58 }
61 59 };
62 60 } else {
63 context.enter(name, this, !!this._services);
64
65 61 // добавляем сервисы
66 62 if (this._services) {
67 63 for (const p of Object.keys(this._services))
@@ -69,23 +65,13 export class ReferenceDescriptor impleme
69 65 }
70 66
71 67 const v = this._optional ?
72 context.getService(this._name, this._default) :
73 context.getService(this._name);
74
75 context.leave();
68 context.resolve(this._name, this._default) :
69 context.resolve(this._name);
76 70
77 71 return v;
78 72 }
79 73 }
80 74
81 isInstanceCreated() {
82 return false;
83 }
84
85 getInstance() {
86 throw new Error("The reference descriptor doesn't allowed to hold an instance");
87 }
88
89 75 toString() {
90 76 const opts = [];
91 77 if (this._optional)
@@ -1,11 +1,14
1 1 import { ActivationContext } from "./ActivationContext";
2 import { Descriptor, ActivationType, ServiceMap } from "./interfaces";
2 import { Descriptor, ActivationType, ServiceMap, isDescriptor } from "./interfaces";
3 3 import { Container } from "./Container";
4 4 import { argumentNotNull, isPrimitive, oid, isPromise } from "../safe";
5 5 import { Constructor, Factory } from "../interfaces";
6 import { TraceSource } from "../log/TraceSource";
6 7
7 8 let cacheId = 0;
8 9
10 const trace = TraceSource.get("@implab/core/di/ActivationContext");
11
9 12 function injectMethod(target, method, context, args) {
10 13 const m = target[method];
11 14 if (!m)
@@ -29,6 +32,24 function makeClenupCallback(target, meth
29 32 }
30 33 }
31 34
35 // TODO: make async
36 function _parse(value, context: ActivationContext, path: string) {
37 if (isPrimitive(value))
38 return value;
39
40 if (isDescriptor(value))
41 return context.activate(value, path);
42
43 if (value instanceof Array)
44 return value.map((x, i) => this._parse(x, context, `${path}[${i}]`));
45
46 const t = {};
47 for (const p of Object.keys(value))
48 t[p] = this._parse(value[p], context, `${path}.${p}`);
49 return t;
50
51 }
52
32 53 export interface ServiceDescriptorParams {
33 54 activation?: ActivationType;
34 55
@@ -119,7 +140,7 export class ServiceDescriptor implement
119 140 }
120 141 }
121 142
122 activate(context: ActivationContext, name: string) {
143 activate(context: ActivationContext) {
123 144 // if we have a local service records, register them first
124 145 let instance;
125 146
@@ -135,7 +156,7 export class ServiceDescriptor implement
135 156 if (container.has(this._cacheId)) {
136 157 instance = container.get(this._cacheId);
137 158 } else {
138 instance = this._create(context, name);
159 instance = this._create(context);
139 160 container.store(this._cacheId, instance);
140 161 if (this._cleanup)
141 162 container.onDispose(
@@ -152,7 +173,7 export class ServiceDescriptor implement
152 173 return this._instance;
153 174
154 175 // create an instance
155 instance = this._create(context, name);
176 instance = this._create(context);
156 177
157 178 // the instance is bound to the container
158 179 if (this._cleanup)
@@ -168,12 +189,10 export class ServiceDescriptor implement
168 189 if (context.has(this._cacheId))
169 190 return context.get(this._cacheId);
170 191 // context context activated instances are controlled by callers
171 return context.store(this._cacheId, this._create(
172 context,
173 name));
192 return context.store(this._cacheId, this._create(context));
174 193 case ActivationType.Call: // CALL
175 194 // per-call created instances are controlled by callers
176 return this._create(context, name);
195 return this._create(context);
177 196 case ActivationType.Hierarchy: // HIERARCHY
178 197 // hierarchy activated instances are behave much like container activated
179 198 // except they are created and bound to the child container
@@ -182,7 +201,7 export class ServiceDescriptor implement
182 201 if (context.container.has(this._cacheId))
183 202 return context.container.get(this._cacheId);
184 203
185 instance = this._create(context, name);
204 instance = this._create(context);
186 205
187 206 if (this._cleanup)
188 207 context.container.onDispose(makeClenupCallback(
@@ -203,8 +222,8 export class ServiceDescriptor implement
203 222 return this._instance;
204 223 }
205 224
206 _create(context, name) {
207 context.enter(name, this, Boolean(this._services));
225 _create(context: ActivationContext) {
226 trace.debug(`constructing ${context._name}`);
208 227
209 228 if (this._activationType !== ActivationType.Call &&
210 229 context.visit(this._cacheId) > 0)
@@ -235,13 +254,9 export class ServiceDescriptor implement
235 254 if (this._params === undefined) {
236 255 instance = this._factory();
237 256 } else if (this._params instanceof Array) {
238 instance = this._factory.apply(this, context.parse(
239 this._params,
240 ".params"));
257 instance = this._factory.apply(this, _parse(this._params, context, "args"));
241 258 } else {
242 instance = this._factory(context.parse(
243 this._params,
244 ".params"));
259 instance = this._factory(_parse(this._params, context, "args"));
245 260 }
246 261
247 262 if (this._inject) {
@@ -251,8 +266,6 export class ServiceDescriptor implement
251 266 });
252 267 }
253 268
254 context.leave();
255
256 269 return instance;
257 270 }
258 271
@@ -1,5 +1,4
1 1 import { Descriptor } from "./interfaces";
2 import { ActivationContext } from "./ActivationContext";
3 2
4 3 export class ValueDescriptor implements Descriptor {
5 4 _value;
@@ -8,16 +7,11 export class ValueDescriptor implements
8 7 this._value = value;
9 8 }
10 9
11 activate(context: ActivationContext, name: string) {
12 context.enter(name);
13 const v = this._value;
14 context.leave();
15 return v;
16 }
17 isInstanceCreated(): boolean {
18 return true;
19 }
20 getInstance() {
10 activate() {
21 11 return this._value;
22 12 }
13
14 toString() {
15 return `@type=${typeof this._value}`;
23 16 }
17 }
@@ -4,8 +4,6 import { Constructor, Factory } from "..
4 4
5 5 export interface Descriptor {
6 6 activate(context: ActivationContext, name?: string);
7 isInstanceCreated(): boolean;
8 getInstance();
9 7 }
10 8
11 9 export function isDescriptor(x): x is Descriptor {
@@ -14,7 +12,7 export function isDescriptor(x): x is De
14 12 }
15 13
16 14 export interface ServiceMap {
17 [s: string]: any;
15 [s: string]: Descriptor;
18 16 }
19 17
20 18 export enum ActivationType {
@@ -1,5 +1,5
1 1 let _nextOid = 0;
2 const _oid = Symbol("__oid");
2 const _oid = typeof Symbol === "function" ? Symbol("__oid") : "__oid";
3 3
4 4 export function oid(instance: object): string {
5 5 if (isNull(instance))
@@ -232,7 +232,7 export function delegate<T, K extends ke
232 232 export function pmap(items, cb) {
233 233 argumentNotNull(cb, "cb");
234 234
235 if (items && items.then instanceof Function)
235 if (isPromise(items))
236 236 return items.then(data => pmap(data, cb));
237 237
238 238 if (isNull(items) || !items.length)
@@ -1,14 +1,26
1 import { test } from "./TestTraits";
1 import { test, TapeWriter } from "./TestTraits";
2 2 import { Container } from "@implab/core/di/Container";
3 3 import { ReferenceDescriptor } from "@implab/core/di/ReferenceDescriptor";
4 4 import { AggregateDescriptor } from "@implab/core/di/AggregateDescriptor";
5 import { ValueDescriptor } from "@implab/core/di/ValueDescriptor";
6 import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource";
7 import { Foo } from "./mock/Foo";
8 import { Bar } from "./mock/Bar";
9 import { isNull } from "@implab/core/safe";
5 10
6 test("Container register/getService tests", async t => {
11 test("Container register/resolve tests", async t => {
12 const writer = new TapeWriter(t);
13
14 TraceSource.on(ts => {
15 ts.level = DebugLevel;
16 writer.writeEvents(ts.events);
17 });
18
7 19 const container = new Container();
8 20
9 21 const connection1 = "db://localhost";
10 22
11 container.register("connection", connection1);
23 container.register("connection", new ValueDescriptor(connection1));
12 24
13 25 t.equals(container.getService("connection"), connection1);
14 26
@@ -21,6 +33,42 test("Container register/getService test
21 33 );
22 34
23 35 const dbParams = container.getService("dbParams");
24 t.equals(dbParams.connection, connection1);
36 t.equals(dbParams.connection, connection1, "should get connection");
37
38 writer.destroy();
39 });
40
41 test("Container configure/resolve tests", async t => {
42 const writer = new TapeWriter(t);
43
44 TraceSource.on(ts => {
45 ts.level = DebugLevel;
46 writer.writeEvents(ts.events);
47 });
48
49 const container = new Container();
50
51 await container.configure({
52 foo: {
53 $type: Foo
54 },
25 55
56 bar: {
57 $type: Bar,
58 params: {
59 db: {
60 provider: {
61 $dependency: "db"
62 }
63 }
64 }
65 }
26 66 });
67
68 const f1 = container.resolve("foo");
69 t.assert(!isNull(f1), "foo should be not null");
70
71 const b1 = container.resolve("bar");
72
73 writer.destroy();
74 });
@@ -66,8 +66,12 export function test(name: string, cb: (
66 66 try {
67 67 await cb(t);
68 68 } catch (e) {
69
70 // verbose error information
71 // tslint:disable-next-line
69 72 console.error(e);
70 73 t.fail(e);
74
71 75 } finally {
72 76 t.end();
73 77 }
@@ -6,7 +6,9
6 6 "outDir" : "build/dist",
7 7 "declaration": true,
8 8 "lib": [
9 "es2015"
9 "es5",
10 "es2015.promise",
11 "es2015.symbol"
10 12 ]
11 13 },
12 14 "include" : [
General Comments 0
You need to be logged in to leave comments. Login now