UNPKG

10.6 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const reflect_1 = require("./reflect");
7const debug_1 = __importDefault(require("debug"));
8const promiseHelpers_1 = require("./promiseHelpers");
9const events_1 = require("events");
10var log = debug_1.default('akala:core:injector');
11function ctorToFunction() {
12 var args = [null];
13 for (var i = 0; i < arguments.length; i++)
14 args[i + 1] = arguments[i];
15 return new (Function.prototype.bind.apply(this, args));
16}
17class Injector {
18 constructor(parent) {
19 this.parent = parent;
20 this.notifier = new events_1.EventEmitter();
21 this.inspecting = false;
22 this.browsingForJSON = false;
23 this.injectables = {};
24 if (this.parent == null)
25 this.parent = exports.defaultInjector;
26 this.register('$injector', this);
27 }
28 setInjectables(value) {
29 this.injectables = value;
30 }
31 keys() {
32 return Object.keys(this.injectables);
33 }
34 merge(i) {
35 var self = this;
36 Object.getOwnPropertyNames(i.injectables).forEach(function (property) {
37 if (property != '$injector')
38 self.registerDescriptor(property, Object.getOwnPropertyDescriptor(i.injectables, property));
39 });
40 }
41 notify(name, value) {
42 if (typeof value == 'undefined')
43 value = Object.getOwnPropertyDescriptor(this.injectables, name);
44 if (this.notifier.listenerCount(name) > 0)
45 this.notifier.emit(name, value);
46 if (this.parent)
47 this.parent.notify(name, value);
48 }
49 onResolve(name, handler) {
50 if (!handler)
51 return new Promise((resolve, reject) => {
52 this.onResolve(name, resolve);
53 });
54 var value = this.resolve(name);
55 if (value !== undefined && value !== null) {
56 handler(value);
57 return;
58 }
59 this.notifier.once(name, (prop) => {
60 if (prop.get)
61 handler(prop.get());
62 else
63 handler(prop.value);
64 });
65 if (this.parent)
66 this.parent.onResolve(name, handler);
67 }
68 inject(a, ...b) {
69 if (typeof a == 'function')
70 return this.injectWithName(a['$inject'] || reflect_1.getParamNames(a), a);
71 var self = this;
72 return function (c) {
73 if (typeof b == 'undefined')
74 b = [];
75 b.unshift(a);
76 var oldf = self.injectWithName(b, c.value);
77 c.value = function () {
78 return oldf.apply(this, arguments);
79 };
80 };
81 }
82 injectAsync(a, ...b) {
83 if (typeof a == 'function')
84 return this.injectWithNameAsync(a['$inject'] || reflect_1.getParamNames(a), a);
85 if (typeof b == 'undefined')
86 b = [];
87 b.unshift(a);
88 var self = this;
89 return function (c) {
90 var f = c.value;
91 c.value = function () {
92 return self.injectWithNameAsync(b, f);
93 };
94 };
95 }
96 injectNew(ctor) {
97 return this.inject(ctorToFunction.bind(ctor));
98 }
99 resolve(param) {
100 log('resolving ' + param);
101 if (typeof (this.injectables[param]) != 'undefined') {
102 log(`resolved ${param}`);
103 log.extend('verbose')(`resolved ${param} to ${this.injectables[param]}`);
104 return this.injectables[param];
105 }
106 var indexOfDot = param.indexOf('.');
107 if (~indexOfDot) {
108 var keys = param.split('.');
109 return keys.reduce((result, key, i) => {
110 if (result instanceof Proxy)
111 return result[key];
112 if (result instanceof Injector)
113 return result.resolve(key);
114 if (promiseHelpers_1.isPromiseLike(result))
115 return result.then((result) => { return result[key]; });
116 if (result === this.injectables && typeof (result[key]) == 'undefined' && this.parent) {
117 return this.parent.resolve(key);
118 }
119 return result && result[key];
120 }, this.injectables);
121 }
122 if (this.parent) {
123 log('trying parent injector');
124 return this.parent.resolve(param);
125 }
126 return null;
127 }
128 resolveAsync(name) {
129 return this.onResolve(name);
130 log('resolving ' + name);
131 if (typeof (this.injectables[name]) != 'undefined') {
132 log('resolved ' + name + ' to %o', this.injectables[name]);
133 return this.injectables[name];
134 }
135 if (this.parent) {
136 log('trying parent injector');
137 return this.parent.resolveAsync(name);
138 }
139 return this.onResolve(name);
140 }
141 inspect() {
142 if (this.inspecting)
143 return;
144 this.inspecting = true;
145 console.log(this.injectables);
146 this.inspecting = false;
147 }
148 toJSON() {
149 console.log(arguments);
150 var wasBrowsingForJSON = this.browsingForJSON;
151 this.browsingForJSON = true;
152 if (!wasBrowsingForJSON)
153 return this.injectables;
154 this.browsingForJSON = wasBrowsingForJSON;
155 return undefined;
156 }
157 injectNewWithName(toInject, ctor) {
158 return this.injectWithName(toInject, ctorToFunction.bind(ctor));
159 }
160 injectWithNameAsync(toInject, a) {
161 if (!toInject || toInject.length == 0)
162 return Promise.resolve(a());
163 var paramNames = reflect_1.getParamNames(a);
164 var self = this;
165 var wait = false;
166 return new Promise((resolve, reject) => {
167 if (paramNames.length == toInject.length || paramNames.length == 0) {
168 if (toInject.length == paramNames.length && paramNames.length == 0)
169 resolve(a.call(null));
170 else {
171 var args = [];
172 for (var param of toInject) {
173 args[args.length] = self.resolveAsync(param);
174 if (promiseHelpers_1.isPromiseLike(args[args.length - 1]))
175 wait = true;
176 }
177 if (wait)
178 return Promise.all(args.map(function (v) {
179 if (promiseHelpers_1.isPromiseLike(v))
180 return v;
181 return Promise.resolve(v);
182 })).then((args) => { resolve(a.apply(null, args)); });
183 else
184 resolve(a.apply(null, args));
185 }
186 }
187 else
188 reject('the number of arguments does not match the number of injected parameters');
189 });
190 }
191 injectWithName(toInject, a) {
192 var self = this;
193 if (toInject && toInject.length > 0) {
194 var paramNames = reflect_1.getParamNames(a);
195 if (paramNames.length == toInject.length || paramNames.length == 0) {
196 if (toInject.length == paramNames.length && paramNames.length == 0)
197 return a;
198 return function (instance) {
199 var args = [];
200 for (var param of toInject) {
201 args[args.length] = self.resolve(param);
202 }
203 return a.apply(instance, args);
204 };
205 }
206 }
207 return function (instance, ...otherArgs) {
208 var args = [];
209 var unknownArgIndex = 0;
210 for (var param of toInject) {
211 var resolved = self.resolve(param);
212 if (resolved && paramNames && paramNames.indexOf(param) == args.length)
213 args[args.length] = resolved;
214 else if (typeof (otherArgs[unknownArgIndex]) != 'undefined')
215 args[args.length] = otherArgs[unknownArgIndex++];
216 else
217 args[args.length] = resolved;
218 }
219 if (otherArgs && otherArgs.length > unknownArgIndex) {
220 args.concat(otherArgs.slice(unknownArgIndex));
221 }
222 return a.apply(instance, args);
223 };
224 }
225 exec(...toInject) {
226 var self = this;
227 return function (f) {
228 return self.injectWithName(toInject, f)(this);
229 };
230 }
231 unregister(name) {
232 var registration = Object.getOwnPropertyDescriptor(this.injectables, name);
233 if (registration)
234 delete this.injectables[name];
235 }
236 register(name, value, override) {
237 if (typeof (value) != 'undefined' && value !== null)
238 this.registerDescriptor(name, { value: value, enumerable: true, configurable: true }, override);
239 return value;
240 }
241 registerFactory(name, value, override) {
242 this.register(name + 'Factory', value, override);
243 this.registerDescriptor(name, {
244 get: function () {
245 return value();
246 }, enumerable: true, configurable: true
247 }, override);
248 return value;
249 }
250 factory(name, override) {
251 var inj = this;
252 return function (fact) {
253 return inj.registerFactory(name, fact, override);
254 };
255 }
256 service(name, override, ...toInject) {
257 var inj = this;
258 var singleton;
259 if (typeof toInject == 'undefined')
260 toInject = [];
261 if (typeof override == 'string') {
262 toInject.unshift(override);
263 override = false;
264 }
265 return function (fact) {
266 inj.registerDescriptor(name, {
267 get() {
268 if (singleton)
269 return singleton;
270 return singleton = inj.injectNewWithName(toInject, fact)();
271 }
272 });
273 };
274 }
275 registerDescriptor(name, value, override) {
276 log('registering ' + name);
277 if (!override && typeof (this.injectables[name]) != 'undefined')
278 throw new Error('There is already a registered item for ' + name);
279 if (typeof (this.injectables[name]) !== 'undefined')
280 this.unregister(name);
281 Object.defineProperty(this.injectables, name, value);
282 this.notify(name, value);
283 }
284}
285exports.Injector = Injector;
286exports.defaultInjector = new Injector();
287//# sourceMappingURL=injector.js.map
\No newline at end of file