##// END OF EJS Templates
working on IoC container
cin -
r38:d3813a6cdb36 di-typescript
parent child
Show More
@@ -1,4 +1,15
1 1 {
2 2 "java.configuration.updateBuildConfiguration": "disabled",
3 "tslint.enable": true
3 "tslint.enable": true,
4 "search.exclude": {
5 "**/node_modules": true,
6 "**/bower_components": true,
7 "/build": true
8 },
9 "files.watcherExclude": {
10 "**/.git/objects/**": true,
11 "**/.git/subtree-cache/**": true,
12 "**/node_modules/**": true,
13 "/build": true
14 }
4 15 } No newline at end of file
@@ -1,11 +1,11
1 import { IActivationController, IActivatable, ICancellation } from '../interfaces';
2 import { AsyncComponent } from './AsyncComponent';
3 import { Cancellation } from '../Cancellation';
4 import { TraceSource } from '../log/TraceSource';
1 import { IActivationController, IActivatable, ICancellation } from "../interfaces";
2 import { AsyncComponent } from "./AsyncComponent";
3 import { Cancellation } from "../Cancellation";
4 import { TraceSource } from "../log/TraceSource";
5 5
6 6 type Constructor<T = {}> = new (...args: any[]) => T;
7 7
8 const log = TraceSource.get('@implab/core/components/ActivatableMixin');
8 const log = TraceSource.get("@implab/core/components/ActivatableMixin");
9 9
10 10 export function ActivatableMixin<TBase extends Constructor<AsyncComponent>>(Base: TBase) {
11 11 return class extends Base implements IActivatable {
@@ -77,7 +77,7 export function ActivatableMixin<TBase e
77 77 log.error("Suppressed onDeactivated error: {0}", e);
78 78 }
79 79 }
80 }
80 };
81 81 }
82 82
83 export const traceSource = log; No newline at end of file
83 export const traceSource = log;
@@ -2,7 +2,7 import { Descriptor } from "./interfaces
2 2 import { ActivationContext } from "./ActivationContext";
3 3
4 4 export class AggregateDescriptor<T> implements Descriptor {
5 _value: T
5 _value: T;
6 6
7 7 constructor(value: T) {
8 8
@@ -10,7 +10,7 export class AggregateDescriptor<T> impl
10 10
11 11 activate(context: ActivationContext, name: string) {
12 12 context.enter(name);
13 let v = context.parse(this._value, ".params");
13 const v = context.parse(this._value, ".params");
14 14 context.leave();
15 15 return v;
16 16 }
@@ -1,28 +1,26
1 declare function require(modules: string[], cb?: (...args: any[]) => any) : void;
2
3 declare function define(name:string, modules: string[], cb?: (...args: any[]) => any) : void;
4
5 import { Uuid } from "../Uuid";
6 1 import { ActivationContext } from "./ActivationContext";
7 2 import { ValueDescriptor } from "./ValueDescriptor";
8 3 import { ActivationError } from "./ActivationError";
9 import { isDescriptor, ActivationType } from "./interfaces";
4 import { isDescriptor, ActivationType, ServiceMap, isDependencyRegistration, isValueRegistration, ServiceRegistration } from "./interfaces";
10 5 import { AggregateDescriptor } from "./AggregateDescriptor";
11 6 import { isPrimitive } from "../safe";
12 7 import { ReferenceDescriptor } from "./ReferenceDescriptor";
13 import { ServiceDescriptor } from "./ServiceDescriptor";
14
8 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
9 import { ModuleResolverBase } from "./ModuleResolverBase";
10 import format = require("../text/format");
15 11
16 12 export class Container {
17 _services
13 _services: ServiceMap;
18 14
19 _cache
15 _cache: object;
16
17 _cleanup: (() => void)[];
20 18
21 _cleanup: any[]
19 _root: Container;
22 20
23 _root: Container
21 _parent: Container;
24 22
25 _parent: Container
23 _resolver: ModuleResolverBase;
26 24
27 25 constructor(parent?: Container) {
28 26 this._parent = parent;
@@ -42,7 +40,7 export class Container {
42 40 }
43 41
44 42 getService<T = any>(name: string, def?: T) {
45 let d = this._services[name];
43 const d = this._services[name];
46 44 if (!d)
47 45 if (arguments.length > 1)
48 46 return def;
@@ -50,21 +48,21 export class Container {
50 48 throw new Error("Service '" + name + "' isn't found");
51 49
52 50 if (d.isInstanceCreated())
53 return d.getInstance();
51 return d.getInstance() as T;
54 52
55 var context = new ActivationContext(this, this._services);
53 const context = new ActivationContext(this, this._services);
56 54
57 55 try {
58 return d.activate(context, name);
56 return d.activate(context, name) as T;
59 57 } catch (error) {
60 58 throw new ActivationError(name, context.getStack(), error);
61 59 }
62 60 }
63 61
64 62 register(nameOrCollection, service?) {
65 if (arguments.length == 1) {
66 var data = nameOrCollection;
67 for (let name in data)
63 if (arguments.length === 1) {
64 const data = nameOrCollection;
65 for (const name in data)
68 66 this.register(name, data[name]);
69 67 } else {
70 68 if (!(isDescriptor(service)))
@@ -82,8 +80,8 export class Container {
82 80
83 81 dispose() {
84 82 if (this._cleanup) {
85 for (var i = 0; i < this._cleanup.length; i++)
86 this._cleanup[i].call(null);
83 for (const f of this._cleanup)
84 f();
87 85 this._cleanup = null;
88 86 }
89 87 }
@@ -93,41 +91,18 export class Container {
93 91 * The configuration of the contaier. Can be either a string or an object,
94 92 * if the configuration is an object it's treated as a collection of
95 93 * services which will be registed in the contaier.
96 *
94 *
97 95 * @param{Function} opts.contextRequire
98 96 * The function which will be used to load a configuration or types for services.
99 *
97 *
100 98 */
101 async configure(config, opts) {
102 var me = this,
103 contextRequire = (opts && opts.contextRequire);
104
99 async configure(config: string | object, opts?: object) {
105 100 if (typeof (config) === "string") {
106 let args;
107 if (!contextRequire) {
108 var shim = [config, Uuid()].join(config.indexOf("/") != -1 ? "-" : "/");
109 args = await new Promise((resolve, reject) => {
110 define(shim, ["require", config], function (ctx, data) {
111 resolve([data, {
112 contextRequire: ctx
113 }]);
114 })
115 });
116 require([shim]);
117 } else {
118 // TODO how to get correct contextRequire for the relative config module?
119 args = await new Promise((resolve, reject) => {
120 contextRequire([config], function (data) {
121 resolve([data, {
122 contextRequire: contextRequire
123 }]);
124 });
125 });
126 }
127
128 return me._configure.apply(me, args);
101 const resolver = await this._resolver.createResolver(config, opts);
102 const data = await this._resolver.loadModule(config);
103 return this._configure(data, { resolver });
129 104 } else {
130 return me._configure(config, opts);
105 return this._configure(config);
131 106 }
132 107 }
133 108
@@ -147,109 +122,108 export class Container {
147 122 return (this._cache[id] = value);
148 123 }
149 124
150 async _configure(data, opts) {
151 var typemap = {},
152 me = this,
153 p,
154 contextRequire = (opts && opts.contextRequire) || require;
125 async _configure(data: object, opts?: { resolver: ModuleResolverBase }) {
126 const resolver = (opts && opts.resolver) || this._resolver;
127
128 const services: ServiceMap = {};
155 129
156 var services = {};
130 resolver.beginBatch();
157 131
158 for (p in data) {
159 var service = me._parse(data[p], typemap);
160 if (!(isDescriptor(service)))
161 service = new AggregateDescriptor(service);
162 services[p] = service;
132 async function parse(k) {
133 services[k] = await this._parse(data[k], resolver);
163 134 }
164 135
165 me.register(services);
136 const batch = Object.keys(data).map(parse);
166 137
167 var names = [];
168
169 for (p in typemap)
170 names.push(p);
138 resolver.completeBatch();
171 139
172 return new Promise((resolve, reject) => {
173 if (names.length) {
174 contextRequire(names, function () {
175 for (var i = 0; i < names.length; i++)
176 typemap[names[i]] = arguments[i];
177 resolve(me);
178 });
179 } else {
180 resolve(me);
181 }
182 });
140 await Promise.all(batch);
183 141
142 this.register(services);
184 143 }
185 144
186 _parse(data, typemap) {
187 if (isPrimitive(data) || isDescriptor(data))
188 return data;
189 if (data.$dependency) {
145 async _parse(registration: any, resolver: ModuleResolverBase) {
146 if (isPrimitive(registration) || isDescriptor(registration))
147 return registration;
148
149 if (isDependencyRegistration(registration)) {
150
190 151 return new ReferenceDescriptor(
191 data.$dependency,
192 data.lazy,
193 data.optional,
194 data["default"],
195 data.services && this._parseObject(data.services, typemap));
196 } else if (data.$value) {
197 return !data.parse ?
198 new ValueDescriptor(data.$value) :
199 new AggregateDescriptor(this._parse(data.$value, typemap));
200 } else if (data.$type || data.$factory) {
201 return this._parseService(data, typemap);
202 } else if (data instanceof Array) {
203 return this._parseArray(data, typemap);
152 registration.$dependency,
153 registration.lazy,
154 registration.optional,
155 registration["default"],
156 registration.services && this._parseObject(registration.services, resolver)
157 );
158
159 } else if (isValueRegistration(registration)) {
160
161 return !registration.parse ?
162 new ValueDescriptor(registration.$value) :
163 new AggregateDescriptor(this._parse(registration.$value, resolver));
164
165 } else if (registration.$type || registration.$factory) {
166 return this._parseService(registration, resolver);
167 } else if (registration instanceof Array) {
168 return this._parseArray(registration, resolver);
204 169 }
205 170
206 return this._parseObject(data, typemap);
171 return this._parseObject(registration, resolver);
207 172 }
208 173
209 _parseService(data, typemap) {
210 var me = this,
211 opts: any = {
212 owner: this
213 };
214 if (data.$type) {
174 async _parseService(data: ServiceRegistration, resolver: ModuleResolverBase) {
175 const opts: ServiceDescriptorParams = {
176 owner: this
177 };
215 178
216 opts.type = data.$type;
217
218 if (typeof (data.$type) === "string") {
219 typemap[data.$type] = null;
220 opts.typeMap = typemap;
221 }
179 function guard<T>(fn: () => PromiseLike<T>) {
180 return fn();
222 181 }
223 182
224 if (data.$factory)
225 opts.factory = data.$factory;
183 if (data.$type) {
184 if (data.$type instanceof Function)
185 opts.type = data.$type;
186 else if (typeof data.$type === "string")
187 opts.type = await resolver.resolve(data.$type);
188 else
189 throw new Error(format("Unsupported type specification: {0:json}", data.$type));
190 } else {
191 if (data.$factory instanceof Function)
192 opts.factory = data.$factory;
193 else if (typeof data.$factory === "string")
194 opts.factory = await resolver.resolve(data.$factory);
195 else
196 throw new Error(format("Unsupported factory specification: {0:json}", data.$factory));
197 }
226 198
227 199 if (data.services)
228 opts.services = me._parseObject(data.services, typemap);
229 if (data.inject)
230 opts.inject = data.inject instanceof Array ? data.inject.map(function (x) {
231 return me._parseObject(x, typemap);
232 }) : me._parseObject(data.inject, typemap);
200 opts.services = await this._parseObject(data.services, resolver);
201
202 if (data.inject instanceof Array)
203 opts.inject = await Promise.all(data.inject.map(x => this._parseObject(x, resolver)));
204 else
205 opts.inject = this._parseObject(data.inject, resolver);
206
233 207 if (data.params)
234 opts.params = me._parse(data.params, typemap);
208 opts.params = this._parse(data.params, resolver);
235 209
236 210 if (data.activation) {
237 211 if (typeof (data.activation) === "string") {
238 212 switch (data.activation.toLowerCase()) {
239 213 case "singleton":
240 opts.activation = ActivationType.SINGLETON;
214 opts.activation = ActivationType.Singleton;
241 215 break;
242 216 case "container":
243 opts.activation = ActivationType.CONTAINER;
217 opts.activation = ActivationType.Container;
244 218 break;
245 219 case "hierarchy":
246 opts.activation = ActivationType.HIERARCHY;
220 opts.activation = ActivationType.Hierarchy;
247 221 break;
248 222 case "context":
249 opts.activation = ActivationType.CONTEXT;
223 opts.activation = ActivationType.Context;
250 224 break;
251 225 case "call":
252 opts.activation = ActivationType.CALL;
226 opts.activation = ActivationType.Call;
253 227 break;
254 228 default:
255 229 throw new Error("Unknown activation type: " +
@@ -266,14 +240,14 export class Container {
266 240 return new ServiceDescriptor(opts);
267 241 }
268 242
269 _parseObject(data, typemap) {
243 _parseObject(data: any, typemap) {
270 244 if (data.constructor &&
271 245 data.constructor.prototype !== Object.prototype)
272 246 return new ValueDescriptor(data);
273 247
274 var o = {};
248 const o = {};
275 249
276 for (var p in data)
250 for (const p in data)
277 251 o[p] = this._parse(data[p], typemap);
278 252
279 253 return o;
@@ -284,9 +258,6 export class Container {
284 258 data.constructor.prototype !== Array.prototype)
285 259 return new ValueDescriptor(data);
286 260
287 var me = this;
288 return data.map(function (x) {
289 return me._parse(x, typemap);
290 });
261 return data.map(x => this._parse(x, typemap));
291 262 }
292 } No newline at end of file
263 }
@@ -2,16 +2,21 import { argumentNotEmptyString, get } f
2 2
3 3 export abstract class ModuleResolverBase {
4 4
5
6 5 async resolve(typeName: string) {
7 6 argumentNotEmptyString(typeName, "typeName");
8 let [moduleName, localName] = typeName.split("#", 2);
7 const [moduleName, localName] = typeName.split("#", 2);
9 8
10 let moduleObject = await this.loadModule(moduleName);
9 const moduleObject = await this.loadModule(moduleName);
11 10 return localName ? get(localName, moduleObject) : moduleObject;
12 11 }
13 12
14 abstract loadModule(moduleName: string): PromiseLike<Object>
13 beginBatch() {
14 }
15 15
16 abstract createResolver(moduleName: string): PromiseLike<ModuleResolverBase>
17 } No newline at end of file
16 completeBatch() {
17 }
18
19 abstract loadModule(moduleName: string): PromiseLike<object>;
20
21 abstract createResolver(moduleName: string, opts?: object): PromiseLike<ModuleResolverBase>;
22 }
@@ -7,18 +7,18 declare function require(modules: string
7 7
8 8 declare function define(name: string, modules: string[], cb?: (...args: any[]) => any): void;
9 9
10 class RequireJsResolverParams {
11 contextRequire: (modules: string[], cb?: (...args: any[]) => any) => void
10 interface RequireJsResolverParams {
11 contextRequire: (modules: string[], cb?: (...args: any[]) => any) => void;
12 12
13 base: string
13 base: string;
14 14 }
15 15
16 16 TraceSource.get("RequireJsResolver");
17 17
18 18 export class RequireJsResolver extends ModuleResolverBase {
19 _contextRequire = require
19 _contextRequire = require;
20 20
21 _base: string
21 _base: string;
22 22
23 23 constructor(opts) {
24 24 super();
@@ -29,7 +29,7 export class RequireJsResolver extends M
29 29 this._contextRequire = opts.contextRequire;
30 30
31 31 if (opts.base) {
32 if (opts.base.indexOf("./") == 0)
32 if (opts.base.indexOf("./") === 0)
33 33 throw new Error(`A module id should be an absolute: '${opts.base}'`);
34 34 this._base = opts.base;
35 35 }
@@ -40,36 +40,35 export class RequireJsResolver extends M
40 40 async createResolver(moduleName: string): Promise<ModuleResolverBase> {
41 41 argumentNotEmptyString(moduleName, "moduleName");
42 42
43 let parts = moduleName.split("/");
44 if (parts[0] == ".") {
43 const parts = moduleName.split("/");
44 if (parts[0] === ".") {
45 45 if (this._base)
46 46 parts[0] = this._base;
47 47 else
48 48 throw new Error(`Can't resolve a relative module '${moduleName}'`);
49 49 }
50 50
51 if(parts.length > 1)
52 parts.splice(-1,1,Uuid());
51 if (parts.length > 1)
52 parts.splice(-1, 1, Uuid());
53 53 else
54 54 parts.push(Uuid());
55 55
56 var shim = parts.join('/');
56 const shim = parts.join("/");
57 57
58 let contextRequire = await new Promise((resolve, reject) => {
59 define(shim, ["require"], function (ctx) {
60 resolve(ctx);
61 })
62 });
58 const contextRequire = await new Promise(
59 resolve => define(shim, ["require"], resolve)
60 );
63 61
64 62 return new RequireJsResolver({
65 base: parts.slice(0,-1).join('/'),
66 contextRequire: contextRequire
63 base: parts.slice(0, -1).join("/"),
64 contextRequire
67 65 });
68 66 }
69 67
70 async loadModule(moduleName: string): Promise<Object> {
71 return new Promise<Object>((resolve) => this._contextRequire.call(null, [moduleName], resolve)
68 async loadModule(moduleName: string): Promise<object> {
69 return new Promise<object>(
70 resolve => this._contextRequire.call(null, [moduleName], resolve)
72 71 );
73 72 }
74 73
75 } No newline at end of file
74 }
@@ -2,11 +2,12 import { ActivationContext } from "./Act
2 2 import { Descriptor, ActivationType, ServiceMap, Constructor, Factory } from "./interfaces";
3 3 import { Container } from "./Container";
4 4 import { argumentNotNull, isPrimitive, oid } from "../safe";
5 import { ClientResponse } from "http";
5 6
6 7 let cacheId = 0;
7 8
8 9 function injectMethod(target, method, context, args) {
9 var m = target[method];
10 const m = target[method];
10 11 if (!m)
11 12 throw new Error("Method '" + method + "' not found");
12 13
@@ -14,60 +15,60 function injectMethod(target, method, co
14 15 m.apply(target, context.parse(args, "." + method));
15 16 else
16 17 m.call(target, context.parse(args, "." + method));
17 };
18 }
18 19
19 function makeClenupCallback(target, method) {
20 function makeClenupCallback(target, method: (instance) => void | string) {
20 21 if (typeof (method) === "string") {
21 return function () {
22 return () => {
22 23 target[method]();
23 24 };
24 25 } else {
25 return function () {
26 return () => {
26 27 method(target);
27 28 };
28 29 }
29 };
30 }
30 31
31 export interface ServiceDescriptorParams<T> {
32 activation: ActivationType
32 export interface ServiceDescriptorParams<T = {}> {
33 activation?: ActivationType;
33 34
34 owner: Container
35 owner: Container;
35 36
36 type: Constructor<T>
37 type?: Constructor<T>;
37 38
38 factory: Factory<T>
39 factory?: Factory<T>;
39 40
40 params
41 params?;
41 42
42 inject
43 inject?;
43 44
44 services: ServiceMap
45 services?: ServiceMap;
45 46
46 cleanup: (instance: T) => void
47 cleanup?: (instance: T) => void | string;
47 48 }
48 49
49 export class ServiceDescriptor<T> implements Descriptor {
50 _instance: T = null
50 export class ServiceDescriptor<T = {}> implements Descriptor {
51 _instance: T = null;
51 52
52 _hasInstance = false
53 _hasInstance = false;
53 54
54 _activationType = ActivationType.CALL
55 _activationType = ActivationType.Call;
55 56
56 _services: ServiceMap
57 _services: ServiceMap;
57 58
58 _type: Constructor<T> = null
59 _type: Constructor<T> = null;
59 60
60 _factory: Factory<T> = null
61 _factory: Factory<T> = null;
61 62
62 _params
63 _params;
63 64
64 _inject: Array<Object>
65 _inject: Array<object>;
65 66
66 _cleanup: (instance: T) => void
67 _cleanup: (instance: T) => void;
67 68
68 _cacheId: any
69 _cacheId: any;
69 70
70 _owner: Container
71 _owner: Container;
71 72
72 73 constructor(opts: ServiceDescriptorParams<T>) {
73 74 argumentNotNull(opts, "opts");
@@ -105,8 +106,8 export class ServiceDescriptor<T> implem
105 106 this._cleanup = opts.cleanup;
106 107 }
107 108
108 if (this._activationType == ActivationType.SINGLETON) {
109 let tof = this._type || this._factory;
109 if (this._activationType === ActivationType.Singleton) {
110 const tof = this._type || this._factory;
110 111
111 112 // create the persistent cache identifier for the type
112 113 if (isPrimitive(tof))
@@ -123,13 +124,13 export class ServiceDescriptor<T> implem
123 124 let instance;
124 125
125 126 switch (this._activationType) {
126 case ActivationType.SINGLETON: // SINGLETON
127 case ActivationType.Singleton: // SINGLETON
127 128 // if the value is cached return it
128 129 if (this._hasInstance)
129 130 return this._instance;
130 131
131 132 // singletons are bound to the root container
132 let container = context.container.getRootContainer();
133 const container = context.container.getRootContainer();
133 134
134 135 if (container.has(this._cacheId)) {
135 136 instance = container.get(this._cacheId);
@@ -144,8 +145,9 export class ServiceDescriptor<T> implem
144 145 this._hasInstance = true;
145 146 return (this._instance = instance);
146 147
147 case ActivationType.CONTAINER: // CONTAINER
148 //return a cached value
148 case ActivationType.Container: // CONTAINER
149 // return a cached value
150
149 151 if (this._hasInstance)
150 152 return this._instance;
151 153
@@ -160,18 +162,19 export class ServiceDescriptor<T> implem
160 162 // cache and return the instance
161 163 this._hasInstance = true;
162 164 return (this._instance = instance);
163 case ActivationType.CONTEXT: // CONTEXT
164 //return a cached value if one exists
165 case ActivationType.Context: // CONTEXT
166 // return a cached value if one exists
167
165 168 if (context.has(this._cacheId))
166 169 return context.get(this._cacheId);
167 // context context activated instances are controlled by callers
170 // context context activated instances are controlled by callers
168 171 return context.store(this._cacheId, this._create(
169 172 context,
170 173 name));
171 case ActivationType.CALL: // CALL
174 case ActivationType.Call: // CALL
172 175 // per-call created instances are controlled by callers
173 176 return this._create(context, name);
174 case ActivationType.HIERARCHY: // HIERARCHY
177 case ActivationType.Hierarchy: // HIERARCHY
175 178 // hierarchy activated instances are behave much like container activated
176 179 // except they are created and bound to the child container
177 180
@@ -188,7 +191,7 export class ServiceDescriptor<T> implem
188 191
189 192 return context.container.store(this._cacheId, instance);
190 193 default:
191 throw "Invalid activation type: " + this._activationType;
194 throw new Error("Invalid activation type: " + this._activationType);
192 195 }
193 196 }
194 197
@@ -203,35 +206,22 export class ServiceDescriptor<T> implem
203 206 _create(context, name) {
204 207 context.enter(name, this, Boolean(this._services));
205 208
206 if (this._activationType != ActivationType.CALL &&
209 if (this._activationType !== ActivationType.Call &&
207 210 context.visit(this._cacheId) > 0)
208 211 throw new Error("Recursion detected");
209 212
210 213 if (this._services) {
211 for (var p in this._services)
214 for (const p in this._services)
212 215 context.register(p, this._services[p]);
213 216 }
214 217
215 var instance;
218 let instance;
216 219
217 220 if (!this._factory) {
218 var ctor = this._type;
219
220 if (this._params === undefined) {
221 this._factory = function () {
222 return new ctor();
223 };
224 } else if (this._params instanceof Array) {
225 this._factory = function () {
226 var inst = Object.create(ctor.prototype);
227 var ret = ctor.apply(inst, arguments);
228 return typeof (ret) === "object" ? ret : inst;
229 };
230 } else {
231 this._factory = function (param) {
232 return new ctor(param);
233 };
234 }
221 const ctor = this._type;
222 this._factory = (...args) => {
223 return new ctor(...args);
224 };
235 225 }
236 226
237 227 if (this._params === undefined) {
@@ -247,8 +237,8 export class ServiceDescriptor<T> implem
247 237 }
248 238
249 239 if (this._inject) {
250 this._inject.forEach(function (spec) {
251 for (var m in spec)
240 this._inject.forEach(spec => {
241 for (const m in spec)
252 242 injectMethod(instance, m, context, spec[m]);
253 243 });
254 244 }
@@ -261,7 +251,7 export class ServiceDescriptor<T> implem
261 251 // @constructor {singleton} foo/bar/Baz
262 252 // @factory {singleton}
263 253 toString() {
264 var parts = [];
254 const parts = [];
265 255
266 256 parts.push(this._type ? "@constructor" : "@factory");
267 257
@@ -272,4 +262,4 export class ServiceDescriptor<T> implem
272 262
273 263 return parts.join(" ");
274 264 }
275 } No newline at end of file
265 }
@@ -3,26 +3,69 import { ActivationContext } from "./Act
3 3
4 4 export interface Descriptor {
5 5 activate(context: ActivationContext, name?: string);
6 isInstanceCreated(): boolean;
7 getInstance();
6 8 }
7 9
8 10 export type Constructor<T = {}> = new (...args: any[]) => T;
9 11
10
11 12 export type Factory<T = {}> = (...args: any[]) => T;
12 13
13 14 export function isDescriptor(instance): instance is Descriptor {
14 return (!isNull(instance)) &&
15 ('activate' in instance);
15 return (!isNull(instance)) &&
16 ("activate" in instance);
16 17 }
17 18
18 19 export interface ServiceMap {
19 [s: string] : Descriptor
20 [s: string]: Descriptor;
20 21 }
21 22
22 23 export enum ActivationType {
23 SINGLETON,
24 CONTAINER,
25 HIERARCHY,
26 CONTEXT,
27 CALL
28 } No newline at end of file
24 Singleton,
25 Container,
26 Hierarchy,
27 Context,
28 Call
29 }
30
31 export interface RegistrationWithServices {
32 services?: object;
33 }
34
35 export interface ServiceRegistration extends RegistrationWithServices {
36 $type?: string | Constructor;
37
38 $factory?: string | Factory;
39
40 activation?: "singleton" | "container" | "hierarchy" | "context" | "call";
41
42 params?;
43
44 inject?: object | object[];
45
46 cleanup: (instance) => void | string;
47 }
48
49 export interface ValueRegistration {
50 $value;
51 parse?: boolean;
52 }
53
54 export interface DependencyRegistration extends RegistrationWithServices {
55 $dependency: string;
56 lazy?: boolean;
57 optional?: boolean;
58 default?;
59 }
60
61 export function isServiceRegistration(x): x is ServiceRegistration {
62 return x && ("$type" in x || "$factory" in x);
63 }
64
65 export function isValueRegistration(x): x is ValueRegistration {
66 return x && "$value" in x;
67 }
68
69 export function isDependencyRegistration(x): x is DependencyRegistration {
70 return x && "$depdendency" in x;
71 }
General Comments 0
You need to be logged in to leave comments. Login now