1 | /*! *****************************************************************************
|
2 | Copyright (c) Microsoft Corporation.
|
3 |
|
4 | Permission to use, copy, modify, and/or distribute this software for any
|
5 | purpose with or without fee is hereby granted.
|
6 |
|
7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
9 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
11 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
12 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
13 | PERFORMANCE OF THIS SOFTWARE.
|
14 | ***************************************************************************** */
|
15 | /* global Reflect, Promise */
|
16 |
|
17 | var extendStatics = function(d, b) {
|
18 | extendStatics = Object.setPrototypeOf ||
|
19 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
20 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
21 | return extendStatics(d, b);
|
22 | };
|
23 |
|
24 | function __extends(d, b) {
|
25 | if (typeof b !== "function" && b !== null)
|
26 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
27 | extendStatics(d, b);
|
28 | function __() { this.constructor = d; }
|
29 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
30 | }
|
31 |
|
32 | var __assign = function() {
|
33 | __assign = Object.assign || function __assign(t) {
|
34 | for (var s, i = 1, n = arguments.length; i < n; i++) {
|
35 | s = arguments[i];
|
36 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
37 | }
|
38 | return t;
|
39 | };
|
40 | return __assign.apply(this, arguments);
|
41 | };
|
42 |
|
43 | function __generator(thisArg, body) {
|
44 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
45 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
46 | function verb(n) { return function (v) { return step([n, v]); }; }
|
47 | function step(op) {
|
48 | if (f) throw new TypeError("Generator is already executing.");
|
49 | while (_) try {
|
50 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
51 | if (y = 0, t) op = [op[0] & 2, t.value];
|
52 | switch (op[0]) {
|
53 | case 0: case 1: t = op; break;
|
54 | case 4: _.label++; return { value: op[1], done: false };
|
55 | case 5: _.label++; y = op[1]; op = [0]; continue;
|
56 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
57 | default:
|
58 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
59 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
60 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
61 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
62 | if (t[2]) _.ops.pop();
|
63 | _.trys.pop(); continue;
|
64 | }
|
65 | op = body.call(thisArg, _);
|
66 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
67 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
68 | }
|
69 | }
|
70 |
|
71 | function __spreadArray(to, from) {
|
72 | for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
73 | to[j] = from[i];
|
74 | return to;
|
75 | }
|
76 |
|
77 | /**
|
78 | * Newline.
|
79 | */
|
80 | var EOL = '\n';
|
81 | /**
|
82 | * An extendable error class.
|
83 | * @author https://github.com/bjyoungblood/es6-error/
|
84 | */
|
85 | var ExtendableError = /** @class */ (function (_super) {
|
86 | __extends(ExtendableError, _super);
|
87 | /**
|
88 | * Constructor for the error.
|
89 | *
|
90 | * @param {String} message
|
91 | * The error message.
|
92 | */
|
93 | function ExtendableError(message) {
|
94 | var _this = _super.call(this, message) || this;
|
95 | // extending Error is weird and does not propagate `message`
|
96 | Object.defineProperty(_this, 'message', {
|
97 | enumerable: false,
|
98 | value: message,
|
99 | });
|
100 | Object.defineProperty(_this, 'name', {
|
101 | enumerable: false,
|
102 | value: _this.constructor.name,
|
103 | });
|
104 | Error.captureStackTrace(_this, _this.constructor);
|
105 | return _this;
|
106 | }
|
107 | return ExtendableError;
|
108 | }(Error));
|
109 | /**
|
110 | * Base error for all Awilix-specific errors.
|
111 | */
|
112 | var AwilixError = /** @class */ (function (_super) {
|
113 | __extends(AwilixError, _super);
|
114 | function AwilixError() {
|
115 | return _super !== null && _super.apply(this, arguments) || this;
|
116 | }
|
117 | return AwilixError;
|
118 | }(ExtendableError));
|
119 | /**
|
120 | * Error thrown to indicate a type mismatch.
|
121 | * TODO(v3): remove `AwilixNotAFunctionError` and use this.
|
122 | */
|
123 | var AwilixTypeError = /** @class */ (function (_super) {
|
124 | __extends(AwilixTypeError, _super);
|
125 | /**
|
126 | * Constructor, takes the function name, expected and given
|
127 | * type to produce an error.
|
128 | *
|
129 | * @param {string} funcDescription
|
130 | * Name of the function being guarded.
|
131 | *
|
132 | * @param {string} paramName
|
133 | * The parameter there was an issue with.
|
134 | *
|
135 | * @param {string} expectedType
|
136 | * Name of the expected type.
|
137 | *
|
138 | * @param {string} givenType
|
139 | * Name of the given type.
|
140 | */
|
141 | function AwilixTypeError(funcDescription, paramName, expectedType, givenType) {
|
142 | return _super.call(this, funcDescription + ": expected " + paramName + " to be " + expectedType + ", but got " + givenType + ".") || this;
|
143 | }
|
144 | /**
|
145 | * Asserts the given condition, throws an error otherwise.
|
146 | *
|
147 | * @param {*} condition
|
148 | * The condition to check
|
149 | *
|
150 | * @param {string} funcDescription
|
151 | * Name of the function being guarded.
|
152 | *
|
153 | * @param {string} paramName
|
154 | * The parameter there was an issue with.
|
155 | *
|
156 | * @param {string} expectedType
|
157 | * Name of the expected type.
|
158 | *
|
159 | * @param {string} givenType
|
160 | * Name of the given type.
|
161 | */
|
162 | AwilixTypeError.assert = function (condition, funcDescription, paramName, expectedType, givenType) {
|
163 | if (!condition) {
|
164 | throw new AwilixTypeError(funcDescription, paramName, expectedType, givenType);
|
165 | }
|
166 | return condition;
|
167 | };
|
168 | return AwilixTypeError;
|
169 | }(AwilixError));
|
170 | /**
|
171 | * A nice error class so we can do an instanceOf check.
|
172 | */
|
173 | var AwilixResolutionError = /** @class */ (function (_super) {
|
174 | __extends(AwilixResolutionError, _super);
|
175 | /**
|
176 | * Constructor, takes the registered modules and unresolved tokens
|
177 | * to create a message.
|
178 | *
|
179 | * @param {string|symbol} name
|
180 | * The name of the module that could not be resolved.
|
181 | *
|
182 | * @param {string[]} resolutionStack
|
183 | * The current resolution stack
|
184 | */
|
185 | function AwilixResolutionError(name, resolutionStack, message) {
|
186 | var _this = this;
|
187 | if (typeof name === 'symbol') {
|
188 | name = name.toString();
|
189 | }
|
190 | resolutionStack = resolutionStack.map(function (val) {
|
191 | return typeof val === 'symbol' ? val.toString() : val;
|
192 | });
|
193 | resolutionStack.push(name);
|
194 | var resolutionPathString = resolutionStack.join(' -> ');
|
195 | var msg = "Could not resolve '" + name + "'.";
|
196 | if (message) {
|
197 | msg += " " + message;
|
198 | }
|
199 | msg += EOL + EOL;
|
200 | msg += "Resolution path: " + resolutionPathString;
|
201 | _this = _super.call(this, msg) || this;
|
202 | return _this;
|
203 | }
|
204 | return AwilixResolutionError;
|
205 | }(AwilixError));
|
206 |
|
207 | /**
|
208 | * Creates a tokenizer for the specified source.
|
209 | *
|
210 | * @param source
|
211 | */
|
212 | function createTokenizer(source) {
|
213 | var end = source.length;
|
214 | var pos = 0;
|
215 | var type = 'EOF';
|
216 | var value = '';
|
217 | var flags = 0 /* None */;
|
218 | // These are used to greedily skip as much as possible.
|
219 | // Whenever we reach a paren, we increment these.
|
220 | var parenLeft = 0;
|
221 | var parenRight = 0;
|
222 | return {
|
223 | next: next,
|
224 | done: done,
|
225 | };
|
226 | /**
|
227 | * Advances the tokenizer and returns the next token.
|
228 | */
|
229 | function next(nextFlags) {
|
230 | if (nextFlags === void 0) { nextFlags = 0 /* None */; }
|
231 | flags = nextFlags;
|
232 | advance();
|
233 | return createToken();
|
234 | }
|
235 | /**
|
236 | * Advances the tokenizer state.
|
237 | */
|
238 | function advance() {
|
239 | value = '';
|
240 | type = 'EOF';
|
241 | while (true) {
|
242 | if (pos >= end) {
|
243 | return (type = 'EOF');
|
244 | }
|
245 | var ch = source.charAt(pos);
|
246 | // Whitespace is irrelevant
|
247 | if (isWhiteSpace(ch)) {
|
248 | pos++;
|
249 | continue;
|
250 | }
|
251 | switch (ch) {
|
252 | case '(':
|
253 | pos++;
|
254 | parenLeft++;
|
255 | return (type = ch);
|
256 | case ')':
|
257 | pos++;
|
258 | parenRight++;
|
259 | return (type = ch);
|
260 | case '*':
|
261 | pos++;
|
262 | return (type = ch);
|
263 | case ',':
|
264 | pos++;
|
265 | return (type = ch);
|
266 | case '=':
|
267 | pos++;
|
268 | if ((flags & 1 /* Dumb */) === 0) {
|
269 | // Not in dumb-mode, so attempt to skip.
|
270 | skipExpression();
|
271 | }
|
272 | // We need to know that there's a default value so we can
|
273 | // skip it if it does not exist when resolving.
|
274 | return (type = ch);
|
275 | case '/':
|
276 | pos++;
|
277 | var nextCh = source.charAt(pos);
|
278 | if (nextCh === '/') {
|
279 | skipUntil(function (c) { return c === '\n'; }, true);
|
280 | pos++;
|
281 | }
|
282 | if (nextCh === '*') {
|
283 | skipUntil(function (c) {
|
284 | var closing = source.charAt(pos + 1);
|
285 | return c === '*' && closing === '/';
|
286 | }, true);
|
287 | pos++;
|
288 | }
|
289 | continue;
|
290 | default:
|
291 | // Scans an identifier.
|
292 | if (isIdentifierStart(ch)) {
|
293 | scanIdentifier();
|
294 | return type;
|
295 | }
|
296 | // Elegantly skip over tokens we don't care about.
|
297 | pos++;
|
298 | }
|
299 | }
|
300 | }
|
301 | /**
|
302 | * Scans an identifier, given it's already been proven
|
303 | * we are ready to do so.
|
304 | */
|
305 | function scanIdentifier() {
|
306 | var identStart = source.charAt(pos);
|
307 | var start = ++pos;
|
308 | while (isIdentifierPart(source.charAt(pos))) {
|
309 | pos++;
|
310 | }
|
311 | value = '' + identStart + source.substring(start, pos);
|
312 | type = value === 'function' || value === 'class' ? value : 'ident';
|
313 | if (type !== 'ident') {
|
314 | value = '';
|
315 | }
|
316 | return value;
|
317 | }
|
318 | /**
|
319 | * Skips everything until the next comma or the end of the parameter list.
|
320 | * Checks the parenthesis balance so we correctly skip function calls.
|
321 | */
|
322 | function skipExpression() {
|
323 | skipUntil(function (ch) {
|
324 | var isAtRoot = parenLeft === parenRight + 1;
|
325 | if (ch === ',' && isAtRoot) {
|
326 | return true;
|
327 | }
|
328 | if (ch === '(') {
|
329 | parenLeft++;
|
330 | return false;
|
331 | }
|
332 | if (ch === ')') {
|
333 | parenRight++;
|
334 | if (isAtRoot) {
|
335 | return true;
|
336 | }
|
337 | }
|
338 | return false;
|
339 | });
|
340 | }
|
341 | /**
|
342 | * Skips strings and whilespace until the predicate is true.
|
343 | *
|
344 | * @param callback stops skipping when this returns `true`.
|
345 | * @param dumb if `true`, does not skip whitespace and strings;
|
346 | * it only stops once the callback returns `true`.
|
347 | */
|
348 | function skipUntil(callback, dumb) {
|
349 | if (dumb === void 0) { dumb = false; }
|
350 | while (pos < source.length) {
|
351 | var ch = source.charAt(pos);
|
352 | if (callback(ch)) {
|
353 | return;
|
354 | }
|
355 | if (!dumb) {
|
356 | if (isWhiteSpace(ch)) {
|
357 | pos++;
|
358 | continue;
|
359 | }
|
360 | if (isStringQuote(ch)) {
|
361 | skipString();
|
362 | continue;
|
363 | }
|
364 | }
|
365 | pos++;
|
366 | }
|
367 | }
|
368 | /**
|
369 | * Given the current position is at a string quote, skips the entire string.
|
370 | */
|
371 | function skipString() {
|
372 | var quote = source.charAt(pos);
|
373 | pos++;
|
374 | while (pos < source.length) {
|
375 | var ch = source.charAt(pos);
|
376 | var prev = source.charAt(pos - 1);
|
377 | // Checks if the quote was escaped.
|
378 | if (ch === quote && prev !== '\\') {
|
379 | pos++;
|
380 | return;
|
381 | }
|
382 | // Template strings are a bit tougher, we want to skip the interpolated values.
|
383 | if (quote === '`') {
|
384 | var next_1 = source.charAt(pos + 1);
|
385 | if (next_1 === '$') {
|
386 | var afterDollar = source.charAt(pos + 2);
|
387 | if (afterDollar === '{') {
|
388 | // This is the start of an interpolation; skip the ${
|
389 | pos = pos + 2;
|
390 | // Skip strings and whitespace until we reach the ending }.
|
391 | // This includes skipping nested interpolated strings. :D
|
392 | skipUntil(function (ch) { return ch === '}'; });
|
393 | }
|
394 | }
|
395 | }
|
396 | pos++;
|
397 | }
|
398 | }
|
399 | /**
|
400 | * Creates a token from the current state.
|
401 | */
|
402 | function createToken() {
|
403 | if (value) {
|
404 | return { value: value, type: type };
|
405 | }
|
406 | return { type: type };
|
407 | }
|
408 | /**
|
409 | * Determines if we are done parsing.
|
410 | */
|
411 | function done() {
|
412 | return type === 'EOF';
|
413 | }
|
414 | }
|
415 | /**
|
416 | * Determines if the given character is a whitespace character.
|
417 | *
|
418 | * @param {string} ch
|
419 | * @return {boolean}
|
420 | */
|
421 | function isWhiteSpace(ch) {
|
422 | switch (ch) {
|
423 | case '\r':
|
424 | case '\n':
|
425 | case ' ':
|
426 | return true;
|
427 | }
|
428 | return false;
|
429 | }
|
430 | /**
|
431 | * Determines if the specified character is a string quote.
|
432 | * @param {string} ch
|
433 | * @return {boolean}
|
434 | */
|
435 | function isStringQuote(ch) {
|
436 | switch (ch) {
|
437 | case "'":
|
438 | case '"':
|
439 | case '`':
|
440 | return true;
|
441 | }
|
442 | return false;
|
443 | }
|
444 | // NOTE: I've added the `.` character so that member expression paths
|
445 | // are seen as identifiers. This is so we don't get a constructor token for
|
446 | // stuff like `MyClass.prototype.constructor()`
|
447 | var IDENT_START_EXPR = /^[_$a-zA-Z\xA0-\uFFFF]$/;
|
448 | var IDENT_PART_EXPR = /^[._$a-zA-Z0-9\xA0-\uFFFF]$/;
|
449 | /**
|
450 | * Determines if the character is a valid JS identifier start character.
|
451 | */
|
452 | function isIdentifierStart(ch) {
|
453 | return IDENT_START_EXPR.test(ch);
|
454 | }
|
455 | /**
|
456 | * Determines if the character is a valid JS identifier start character.
|
457 | */
|
458 | function isIdentifierPart(ch) {
|
459 | return IDENT_PART_EXPR.test(ch);
|
460 | }
|
461 |
|
462 | /**
|
463 | * Creates a { name: value } object if the input isn't already in that format.
|
464 | *
|
465 | * @param {string|object} name
|
466 | * Either a string or an object.
|
467 | *
|
468 | * @param {*} value
|
469 | * The value, only used if name is not an object.
|
470 | *
|
471 | * @return {object}
|
472 | */
|
473 | function nameValueToObject(name, value) {
|
474 | var _a;
|
475 | var obj = name;
|
476 | if (typeof obj === 'string' || typeof obj === 'symbol') {
|
477 | return _a = {}, _a[name] = value, _a;
|
478 | }
|
479 | return obj;
|
480 | }
|
481 | /**
|
482 | * Returns the last item in the array.
|
483 | *
|
484 | * @param {*[]} arr
|
485 | * The array.
|
486 | *
|
487 | * @return {*}
|
488 | * The last element.
|
489 | */
|
490 | function last(arr) {
|
491 | return arr[arr.length - 1];
|
492 | }
|
493 | /**
|
494 | * Determines if the given function is a class.
|
495 | *
|
496 | * @param {Function} fn
|
497 | * @return {boolean}
|
498 | */
|
499 | function isClass(fn) {
|
500 | /*tslint:disable-next-line*/
|
501 | if (typeof fn !== 'function') {
|
502 | return false;
|
503 | }
|
504 | // Should only need 2 tokens.
|
505 | var tokenizer = createTokenizer(fn.toString());
|
506 | var first = tokenizer.next();
|
507 | if (first.type === 'class') {
|
508 | return true;
|
509 | }
|
510 | var second = tokenizer.next();
|
511 | if (first.type === 'function' && second.value) {
|
512 | if (second.value[0] === second.value[0].toUpperCase()) {
|
513 | return true;
|
514 | }
|
515 | }
|
516 | return false;
|
517 | }
|
518 | /**
|
519 | * Determines if the given value is a function.
|
520 | *
|
521 | * @param {Any} val
|
522 | * Any value to check if it's a function.
|
523 | *
|
524 | * @return {boolean}
|
525 | * true if the value is a function, false otherwise.
|
526 | */
|
527 | function isFunction(val) {
|
528 | return typeof val === 'function';
|
529 | }
|
530 | /**
|
531 | * Returns the unique items in the array.
|
532 | *
|
533 | * @param {Array<T>}
|
534 | * The array to remove dupes from.
|
535 | *
|
536 | * @return {Array<T>}
|
537 | * The deduped array.
|
538 | */
|
539 | function uniq(arr) {
|
540 | return Array.from(new Set(arr));
|
541 | }
|
542 |
|
543 | /**
|
544 | * Lifetime types.
|
545 | */
|
546 | var Lifetime = {
|
547 | /**
|
548 | * The registration will be resolved once and only once.
|
549 | * @type {String}
|
550 | */
|
551 | SINGLETON: 'SINGLETON',
|
552 | /**
|
553 | * The registration will be resolved every time (never cached).
|
554 | * @type {String}
|
555 | */
|
556 | TRANSIENT: 'TRANSIENT',
|
557 | /**
|
558 | * The registration will be resolved once per scope.
|
559 | * @type {String}
|
560 | */
|
561 | SCOPED: 'SCOPED',
|
562 | };
|
563 |
|
564 | /**
|
565 | * Resolution modes.
|
566 | */
|
567 | var InjectionMode = {
|
568 | /**
|
569 | * The dependencies will be resolved by injecting the cradle proxy.
|
570 | *
|
571 | * @type {String}
|
572 | */
|
573 | PROXY: 'PROXY',
|
574 | /**
|
575 | * The dependencies will be resolved by inspecting parameter names of the function/constructor.
|
576 | *
|
577 | * @type {String}
|
578 | */
|
579 | CLASSIC: 'CLASSIC',
|
580 | };
|
581 |
|
582 | /*
|
583 | * Parses the parameter list of a function string, including ES6 class constructors.
|
584 | *
|
585 | * @param {string} source
|
586 | * The source of a function to extract the parameter list from
|
587 | *
|
588 | * @return {Array<Parameter> | null}
|
589 | * Returns an array of parameters, or `null` if no
|
590 | * constructor was found for a class.
|
591 | */
|
592 | function parseParameterList(source) {
|
593 | var _a = createTokenizer(source), _next = _a.next, done = _a.done;
|
594 | var params = [];
|
595 | var t = null;
|
596 | nextToken();
|
597 | while (!done()) {
|
598 | switch (t.type) {
|
599 | case 'class':
|
600 | skipUntilConstructor();
|
601 | // If we didn't find a constructor token, then we know that there
|
602 | // are no dependencies in the defined class.
|
603 | if (!isConstructorToken()) {
|
604 | return null;
|
605 | }
|
606 | // Next token is the constructor identifier.
|
607 | nextToken();
|
608 | break;
|
609 | case 'function':
|
610 | var next = nextToken();
|
611 | if (next.type === 'ident' || next.type === '*') {
|
612 | // This is the function name or a generator star. Skip it.
|
613 | nextToken();
|
614 | }
|
615 | break;
|
616 | case '(':
|
617 | // Start parsing parameter names.
|
618 | parseParams();
|
619 | break;
|
620 | case ')':
|
621 | // We're now out of the parameter list.
|
622 | return params;
|
623 | case 'ident':
|
624 | // Likely a paren-less arrow function
|
625 | // which can have no default args.
|
626 | var param = { name: t.value, optional: false };
|
627 | if (t.value === 'async') {
|
628 | // Given it's the very first token, we can assume it's an async function,
|
629 | // so skip the async keyword if the next token is not an equals sign, in which
|
630 | // case it is a single-arg arrow func.
|
631 | var next_1 = nextToken();
|
632 | if (next_1 && next_1.type !== '=') {
|
633 | break;
|
634 | }
|
635 | }
|
636 | params.push(param);
|
637 | return params;
|
638 | /* istanbul ignore next */
|
639 | default:
|
640 | throw unexpected();
|
641 | }
|
642 | }
|
643 | return params;
|
644 | /**
|
645 | * After having been placed within the parameter list of
|
646 | * a function, parses the parameters.
|
647 | */
|
648 | function parseParams() {
|
649 | // Current token is a left-paren
|
650 | var param = { name: '', optional: false };
|
651 | while (!done()) {
|
652 | nextToken();
|
653 | switch (t.type) {
|
654 | case 'ident':
|
655 | param.name = t.value;
|
656 | break;
|
657 | case '=':
|
658 | param.optional = true;
|
659 | break;
|
660 | case ',':
|
661 | params.push(param);
|
662 | param = { name: '', optional: false };
|
663 | break;
|
664 | case ')':
|
665 | if (param.name) {
|
666 | params.push(param);
|
667 | }
|
668 | return;
|
669 | /* istanbul ignore next */
|
670 | default:
|
671 | throw unexpected();
|
672 | }
|
673 | }
|
674 | }
|
675 | /**
|
676 | * Skips until we reach the constructor identifier.
|
677 | */
|
678 | function skipUntilConstructor() {
|
679 | while (!isConstructorToken() && !done()) {
|
680 | nextToken(1 /* Dumb */);
|
681 | }
|
682 | }
|
683 | /**
|
684 | * Determines if the current token represents a constructor, and the next token after it is a paren
|
685 | * @return {boolean}
|
686 | */
|
687 | function isConstructorToken() {
|
688 | return t.type === 'ident' && t.value === 'constructor';
|
689 | }
|
690 | /**
|
691 | * Advances the tokenizer and stores the previous token in history
|
692 | */
|
693 | function nextToken(flags) {
|
694 | if (flags === void 0) { flags = 0 /* None */; }
|
695 | t = _next(flags);
|
696 | return t;
|
697 | }
|
698 | /**
|
699 | * Returns an error describing an unexpected token.
|
700 | */
|
701 | /* istanbul ignore next */
|
702 | function unexpected() {
|
703 | return new SyntaxError("Parsing parameter list, did not expect " + t.type + " token" + (t.value ? " (" + t.value + ")" : ''));
|
704 | }
|
705 | }
|
706 |
|
707 | /**
|
708 | * RESOLVER symbol can be used by modules loaded by
|
709 | * `loadModules` to configure their lifetime, injection mode, etc.
|
710 | */
|
711 | var RESOLVER = Symbol('Awilix Resolver Config');
|
712 | /**
|
713 | * Creates a simple value resolver where the given value will always be resolved.
|
714 | *
|
715 | * @param {string} name
|
716 | * The name to register the value as.
|
717 | *
|
718 | * @param {*} value
|
719 | * The value to resolve.
|
720 | *
|
721 | * @return {object}
|
722 | * The resolver.
|
723 | */
|
724 | function asValue(value) {
|
725 | return {
|
726 | resolve: function () { return value; },
|
727 | };
|
728 | }
|
729 | /**
|
730 | * Creates a factory resolver, where the given factory function
|
731 | * will be invoked with `new` when requested.
|
732 | *
|
733 | * @param {string} name
|
734 | * The name to register the value as.
|
735 | *
|
736 | * @param {Function} fn
|
737 | * The function to register.
|
738 | *
|
739 | * @param {object} opts
|
740 | * Additional options for the resolver.
|
741 | *
|
742 | * @return {object}
|
743 | * The resolver.
|
744 | */
|
745 | function asFunction(fn, opts) {
|
746 | if (!isFunction(fn)) {
|
747 | throw new AwilixTypeError('asFunction', 'fn', 'function', fn);
|
748 | }
|
749 | var defaults = {
|
750 | lifetime: Lifetime.TRANSIENT,
|
751 | };
|
752 | opts = makeOptions(defaults, opts, fn[RESOLVER]);
|
753 | var resolve = generateResolve(fn);
|
754 | var result = __assign({ resolve: resolve }, opts);
|
755 | return createDisposableResolver(createBuildResolver(result));
|
756 | }
|
757 | /**
|
758 | * Like a factory resolver, but for classes that require `new`.
|
759 | *
|
760 | * @param {string} name
|
761 | * The name to register the value as.
|
762 | *
|
763 | * @param {Class} Type
|
764 | * The function to register.
|
765 | *
|
766 | * @param {object} opts
|
767 | * Additional options for the resolver.
|
768 | *
|
769 | * @return {object}
|
770 | * The resolver.
|
771 | */
|
772 | function asClass(Type, opts) {
|
773 | if (!isFunction(Type)) {
|
774 | throw new AwilixTypeError('asClass', 'Type', 'class', Type);
|
775 | }
|
776 | var defaults = {
|
777 | lifetime: Lifetime.TRANSIENT,
|
778 | };
|
779 | opts = makeOptions(defaults, opts, Type[RESOLVER]);
|
780 | // A function to handle object construction for us, as to make the generateResolve more reusable
|
781 | var newClass = function newClass() {
|
782 | return Reflect.construct(Type, arguments);
|
783 | };
|
784 | var resolve = generateResolve(newClass, Type);
|
785 | return createDisposableResolver(createBuildResolver(__assign(__assign({}, opts), { resolve: resolve })));
|
786 | }
|
787 | /**
|
788 | * Resolves to the specified registration.
|
789 | */
|
790 | function aliasTo(name) {
|
791 | return {
|
792 | resolve: function (container) {
|
793 | return container.resolve(name);
|
794 | },
|
795 | };
|
796 | }
|
797 | /**
|
798 | * Given an options object, creates a fluid interface
|
799 | * to manage it.
|
800 | *
|
801 | * @param {*} obj
|
802 | * The object to return.
|
803 | *
|
804 | * @return {object}
|
805 | * The interface.
|
806 | */
|
807 | function createBuildResolver(obj) {
|
808 | function setLifetime(value) {
|
809 | return createBuildResolver(__assign(__assign({}, this), { lifetime: value }));
|
810 | }
|
811 | function setInjectionMode(value) {
|
812 | return createBuildResolver(__assign(__assign({}, this), { injectionMode: value }));
|
813 | }
|
814 | function inject(injector) {
|
815 | return createBuildResolver(__assign(__assign({}, this), { injector: injector }));
|
816 | }
|
817 | return updateResolver(obj, {
|
818 | setLifetime: setLifetime,
|
819 | inject: inject,
|
820 | transient: partial(setLifetime, Lifetime.TRANSIENT),
|
821 | scoped: partial(setLifetime, Lifetime.SCOPED),
|
822 | singleton: partial(setLifetime, Lifetime.SINGLETON),
|
823 | setInjectionMode: setInjectionMode,
|
824 | proxy: partial(setInjectionMode, InjectionMode.PROXY),
|
825 | classic: partial(setInjectionMode, InjectionMode.CLASSIC),
|
826 | });
|
827 | }
|
828 | /**
|
829 | * Given a resolver, returns an object with methods to manage the disposer
|
830 | * function.
|
831 | * @param obj
|
832 | */
|
833 | function createDisposableResolver(obj) {
|
834 | function disposer(dispose) {
|
835 | return createDisposableResolver(__assign(__assign({}, this), { dispose: dispose }));
|
836 | }
|
837 | return updateResolver(obj, {
|
838 | disposer: disposer,
|
839 | });
|
840 | }
|
841 | /**
|
842 | * Partially apply arguments to the given function.
|
843 | */
|
844 | function partial(fn, arg1) {
|
845 | return function partiallyApplied() {
|
846 | return fn.call(this, arg1);
|
847 | };
|
848 | }
|
849 | /**
|
850 | * Makes an options object based on defaults.
|
851 | *
|
852 | * @param {object} defaults
|
853 | * Default options.
|
854 | *
|
855 | * @param {...} rest
|
856 | * The input to check and possibly assign to the resulting object
|
857 | *
|
858 | * @return {object}
|
859 | */
|
860 | function makeOptions(defaults) {
|
861 | var rest = [];
|
862 | for (var _i = 1; _i < arguments.length; _i++) {
|
863 | rest[_i - 1] = arguments[_i];
|
864 | }
|
865 | return Object.assign.apply(Object, __spreadArray([{}, defaults], rest));
|
866 | }
|
867 | /**
|
868 | * Creates a new resolver with props merged from both.
|
869 | *
|
870 | * @param source
|
871 | * @param target
|
872 | */
|
873 | function updateResolver(source, target) {
|
874 | var result = __assign(__assign({}, source), target);
|
875 | return result;
|
876 | }
|
877 | /**
|
878 | * Returns a wrapped `resolve` function that provides values
|
879 | * from the injector and defers to `container.resolve`.
|
880 | *
|
881 | * @param {AwilixContainer} container
|
882 | * @param {Object} locals
|
883 | * @return {Function}
|
884 | */
|
885 | function wrapWithLocals(container, locals) {
|
886 | return function wrappedResolve(name, resolveOpts) {
|
887 | if (name in locals) {
|
888 | return locals[name];
|
889 | }
|
890 | return container.resolve(name, resolveOpts);
|
891 | };
|
892 | }
|
893 | /**
|
894 | * Returns a new Proxy that checks the result from `injector`
|
895 | * for values before delegating to the actual container.
|
896 | *
|
897 | * @param {Object} cradle
|
898 | * @param {Function} injector
|
899 | * @return {Proxy}
|
900 | */
|
901 | function createInjectorProxy(container, injector) {
|
902 | var locals = injector(container);
|
903 | var allKeys = uniq(__spreadArray(__spreadArray([], Reflect.ownKeys(container.cradle), true), Reflect.ownKeys(locals)));
|
904 | // TODO: Lots of duplication here from the container proxy.
|
905 | // Need to refactor.
|
906 | var proxy = new Proxy({}, {
|
907 | /**
|
908 | * Resolves the value by first checking the locals, then the container.
|
909 | */
|
910 | get: function (target, name) {
|
911 | if (name === Symbol.iterator) {
|
912 | return function iterateRegistrationsAndLocals() {
|
913 | var _a, _b, _i, prop, _c, _d, _e, prop;
|
914 | return __generator(this, function (_f) {
|
915 | switch (_f.label) {
|
916 | case 0:
|
917 | _a = [];
|
918 | for (_b in container.cradle)
|
919 | _a.push(_b);
|
920 | _i = 0;
|
921 | _f.label = 1;
|
922 | case 1:
|
923 | if (!(_i < _a.length)) return [3 /*break*/, 4];
|
924 | prop = _a[_i];
|
925 | return [4 /*yield*/, prop];
|
926 | case 2:
|
927 | _f.sent();
|
928 | _f.label = 3;
|
929 | case 3:
|
930 | _i++;
|
931 | return [3 /*break*/, 1];
|
932 | case 4:
|
933 | _c = [];
|
934 | for (_d in locals)
|
935 | _c.push(_d);
|
936 | _e = 0;
|
937 | _f.label = 5;
|
938 | case 5:
|
939 | if (!(_e < _c.length)) return [3 /*break*/, 8];
|
940 | prop = _c[_e];
|
941 | return [4 /*yield*/, prop];
|
942 | case 6:
|
943 | _f.sent();
|
944 | _f.label = 7;
|
945 | case 7:
|
946 | _e++;
|
947 | return [3 /*break*/, 5];
|
948 | case 8: return [2 /*return*/];
|
949 | }
|
950 | });
|
951 | };
|
952 | }
|
953 | if (name in locals) {
|
954 | return locals[name];
|
955 | }
|
956 | return container.resolve(name);
|
957 | },
|
958 | /**
|
959 | * Used for `Object.keys`.
|
960 | */
|
961 | ownKeys: function () {
|
962 | return allKeys;
|
963 | },
|
964 | /**
|
965 | * Used for `Object.keys`.
|
966 | */
|
967 | getOwnPropertyDescriptor: function (target, key) {
|
968 | if (allKeys.indexOf(key) > -1) {
|
969 | return {
|
970 | enumerable: true,
|
971 | configurable: true,
|
972 | };
|
973 | }
|
974 | return undefined;
|
975 | },
|
976 | });
|
977 | return proxy;
|
978 | }
|
979 | /**
|
980 | * Returns a resolve function used to construct the dependency graph
|
981 | *
|
982 | * @this {Registration}
|
983 | * The `this` context is a resolver.
|
984 | *
|
985 | * @param {Function} fn
|
986 | * The function to construct
|
987 | *
|
988 | * @param {Function} dependencyParseTarget
|
989 | * The function to parse for the dependencies of the construction target
|
990 | *
|
991 | * @param {boolean} isFunction
|
992 | * Is the resolution target an actual function or a mask for a constructor?
|
993 | *
|
994 | * @return {Function}
|
995 | * The function used for dependency resolution
|
996 | */
|
997 | function generateResolve(fn, dependencyParseTarget) {
|
998 | // If the function used for dependency parsing is falsy, use the supplied function
|
999 | if (!dependencyParseTarget) {
|
1000 | dependencyParseTarget = fn;
|
1001 | }
|
1002 | // Parse out the dependencies
|
1003 | // NOTE: we do this regardless of whether PROXY is used or not,
|
1004 | // because if this fails, we want it to fail early (at startup) rather
|
1005 | // than at resolution time.
|
1006 | var dependencies = parseDependencies(dependencyParseTarget);
|
1007 | // Use a regular function instead of an arrow function to facilitate binding to the resolver.
|
1008 | return function resolve(container) {
|
1009 | // Because the container holds a global reolutionMode we need to determine it in the proper order of precedence:
|
1010 | // resolver -> container -> default value
|
1011 | var injectionMode = this.injectionMode ||
|
1012 | container.options.injectionMode ||
|
1013 | InjectionMode.PROXY;
|
1014 | if (injectionMode !== InjectionMode.CLASSIC) {
|
1015 | // If we have a custom injector, we need to wrap the cradle.
|
1016 | var cradle = this.injector
|
1017 | ? createInjectorProxy(container, this.injector)
|
1018 | : container.cradle;
|
1019 | // Return the target injected with the cradle
|
1020 | return fn(cradle);
|
1021 | }
|
1022 | // We have dependencies so we need to resolve them manually
|
1023 | if (dependencies.length > 0) {
|
1024 | var resolve_1 = this.injector
|
1025 | ? wrapWithLocals(container, this.injector(container))
|
1026 | : container.resolve;
|
1027 | var children = dependencies.map(function (p) {
|
1028 | return resolve_1(p.name, { allowUnregistered: p.optional });
|
1029 | });
|
1030 | return fn.apply(void 0, children);
|
1031 | }
|
1032 | return fn();
|
1033 | };
|
1034 | }
|
1035 | /**
|
1036 | * Parses the dependencies from the given function.
|
1037 | * If it's a class that extends another class, and it does
|
1038 | * not have a defined constructor, attempt to parse it's super constructor.
|
1039 | */
|
1040 | function parseDependencies(fn) {
|
1041 | var result = parseParameterList(fn.toString());
|
1042 | if (!result) {
|
1043 | // No defined constructor for a class, check if there is a parent
|
1044 | // we can parse.
|
1045 | var parent = Object.getPrototypeOf(fn);
|
1046 | if (typeof parent === 'function' && parent !== Function.prototype) {
|
1047 | // Try to parse the parent
|
1048 | return parseDependencies(parent);
|
1049 | }
|
1050 | return [];
|
1051 | }
|
1052 | return result;
|
1053 | }
|
1054 |
|
1055 | /**
|
1056 | * Family tree symbol.
|
1057 | */
|
1058 | var FAMILY_TREE = Symbol('familyTree');
|
1059 | /**
|
1060 | * Roll Up Registrations symbol.
|
1061 | */
|
1062 | var ROLL_UP_REGISTRATIONS = Symbol('rollUpRegistrations');
|
1063 | /**
|
1064 | * Creates an Awilix container instance.
|
1065 | *
|
1066 | * @param {Function} options.require
|
1067 | * The require function to use. Defaults to require.
|
1068 | *
|
1069 | * @param {string} options.injectionMode
|
1070 | * The mode used by the container to resolve dependencies. Defaults to 'Proxy'.
|
1071 | *
|
1072 | * @return {AwilixContainer<T>}
|
1073 | * The container.
|
1074 | */
|
1075 | function createContainer(options, parentContainer) {
|
1076 | var _a;
|
1077 | options = __assign({ injectionMode: InjectionMode.PROXY }, options);
|
1078 | // The resolution stack is used to keep track
|
1079 | // of what modules are being resolved, so when
|
1080 | // an error occurs, we have something to present
|
1081 | // to the poor developer who fucked up.
|
1082 | var resolutionStack = [];
|
1083 | // Internal registration store for this container.
|
1084 | var registrations = {};
|
1085 | /**
|
1086 | * The `Proxy` that is passed to functions so they can resolve their dependencies without
|
1087 | * knowing where they come from. I call it the "cradle" because
|
1088 | * it is where registered things come to life at resolution-time.
|
1089 | */
|
1090 | var cradle = new Proxy({
|
1091 | /* removed in browser build */
|
1092 | }, {
|
1093 | /**
|
1094 | * The `get` handler is invoked whenever a get-call for `container.cradle.*` is made.
|
1095 | *
|
1096 | * @param {object} _target
|
1097 | * The proxy target. Irrelevant.
|
1098 | *
|
1099 | * @param {string} name
|
1100 | * The property name.
|
1101 | *
|
1102 | * @return {*}
|
1103 | * Whatever the resolve call returns.
|
1104 | */
|
1105 | get: function (_target, name) { return resolve(name); },
|
1106 | /**
|
1107 | * Setting things on the cradle throws an error.
|
1108 | *
|
1109 | * @param {object} target
|
1110 | * @param {string} name
|
1111 | */
|
1112 | set: function (_target, name) {
|
1113 | throw new Error("Attempted setting property \"" + name + "\" on container cradle - this is not allowed.");
|
1114 | },
|
1115 | /**
|
1116 | * Used for `Object.keys`.
|
1117 | */
|
1118 | ownKeys: function () {
|
1119 | return Array.from(cradle);
|
1120 | },
|
1121 | /**
|
1122 | * Used for `Object.keys`.
|
1123 | */
|
1124 | getOwnPropertyDescriptor: function (target, key) {
|
1125 | var regs = rollUpRegistrations();
|
1126 | if (Object.getOwnPropertyDescriptor(regs, key)) {
|
1127 | return {
|
1128 | enumerable: true,
|
1129 | configurable: true,
|
1130 | };
|
1131 | }
|
1132 | return undefined;
|
1133 | },
|
1134 | });
|
1135 | // The container being exposed.
|
1136 | var container = (_a = {
|
1137 | options: options,
|
1138 | cradle: cradle,
|
1139 | inspect: inspect,
|
1140 | cache: new Map(),
|
1141 | loadModules: function () { throw new Error("loadModules is not supported in the browser."); },
|
1142 | createScope: createScope,
|
1143 | register: register,
|
1144 | build: build,
|
1145 | resolve: resolve,
|
1146 | hasRegistration: hasRegistration,
|
1147 | dispose: dispose,
|
1148 | getRegistration: getRegistration
|
1149 | },
|
1150 | /* removed in browser build */
|
1151 | // tslint:disable-next-line
|
1152 | _a[ROLL_UP_REGISTRATIONS] = rollUpRegistrations,
|
1153 | Object.defineProperty(_a, "registrations", {
|
1154 | get: function () {
|
1155 | return rollUpRegistrations();
|
1156 | },
|
1157 | enumerable: false,
|
1158 | configurable: true
|
1159 | }),
|
1160 | _a);
|
1161 | // Track the family tree.
|
1162 | var familyTree = parentContainer
|
1163 | ? [container].concat(parentContainer[FAMILY_TREE])
|
1164 | : [container];
|
1165 | container[FAMILY_TREE] = familyTree;
|
1166 | // We need a reference to the root container,
|
1167 | // so we can retrieve and store singletons.
|
1168 | var rootContainer = last(familyTree);
|
1169 | return container;
|
1170 | /**
|
1171 | * Used by util.inspect (which is used by console.log).
|
1172 | */
|
1173 | function inspect() {
|
1174 | return "[AwilixContainer (" + (parentContainer ? 'scoped, ' : '') + "registrations: " + Object.keys(container.registrations).length + ")]";
|
1175 | }
|
1176 | /**
|
1177 | * Rolls up registrations from the family tree.
|
1178 | *
|
1179 | * This can get pretty expensive. Only used when
|
1180 | * iterating the cradle proxy, which is not something
|
1181 | * that should be done in day-to-day use, mostly for debugging.
|
1182 | *
|
1183 | * @param {boolean} bustCache
|
1184 | * Forces a recomputation.
|
1185 | *
|
1186 | * @return {object}
|
1187 | * The merged registrations object.
|
1188 | */
|
1189 | function rollUpRegistrations() {
|
1190 | return __assign(__assign({}, (parentContainer && parentContainer[ROLL_UP_REGISTRATIONS]())), registrations);
|
1191 | }
|
1192 | /**
|
1193 | * Used for providing an iterator to the cradle.
|
1194 | */
|
1195 | function cradleIterator() {
|
1196 | var registrations, _a, _b, _i, registrationName;
|
1197 | return __generator(this, function (_c) {
|
1198 | switch (_c.label) {
|
1199 | case 0:
|
1200 | registrations = rollUpRegistrations();
|
1201 | _a = [];
|
1202 | for (_b in registrations)
|
1203 | _a.push(_b);
|
1204 | _i = 0;
|
1205 | _c.label = 1;
|
1206 | case 1:
|
1207 | if (!(_i < _a.length)) return [3 /*break*/, 4];
|
1208 | registrationName = _a[_i];
|
1209 | return [4 /*yield*/, registrationName];
|
1210 | case 2:
|
1211 | _c.sent();
|
1212 | _c.label = 3;
|
1213 | case 3:
|
1214 | _i++;
|
1215 | return [3 /*break*/, 1];
|
1216 | case 4: return [2 /*return*/];
|
1217 | }
|
1218 | });
|
1219 | }
|
1220 | /**
|
1221 | * Creates a scoped container.
|
1222 | *
|
1223 | * @return {object}
|
1224 | * The scoped container.
|
1225 | */
|
1226 | function createScope() {
|
1227 | return createContainer(options, container);
|
1228 | }
|
1229 | /**
|
1230 | * Adds a registration for a resolver.
|
1231 | */
|
1232 | function register(arg1, arg2) {
|
1233 | var obj = nameValueToObject(arg1, arg2);
|
1234 | var keys = __spreadArray(__spreadArray([], Object.keys(obj), true), Object.getOwnPropertySymbols(obj));
|
1235 | for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
|
1236 | var key = keys_1[_i];
|
1237 | var value = obj[key];
|
1238 | registrations[key] = value;
|
1239 | }
|
1240 | return container;
|
1241 | }
|
1242 | /**
|
1243 | * Returned to `util.inspect` when attempting to resolve
|
1244 | * a custom inspector function on the cradle.
|
1245 | */
|
1246 | function inspectCradle() {
|
1247 | return '[AwilixContainer.cradle]';
|
1248 | }
|
1249 | /**
|
1250 | * Recursively gets a registration by name if it exists in the
|
1251 | * current container or any of its' parents.
|
1252 | *
|
1253 | * @param name {string | symbol} The registration name.
|
1254 | */
|
1255 | function getRegistration(name) {
|
1256 | var resolver = registrations[name];
|
1257 | if (resolver) {
|
1258 | return resolver;
|
1259 | }
|
1260 | if (parentContainer) {
|
1261 | return parentContainer.getRegistration(name);
|
1262 | }
|
1263 | return null;
|
1264 | }
|
1265 | /**
|
1266 | * Resolves the registration with the given name.
|
1267 | *
|
1268 | * @param {string | symbol} name
|
1269 | * The name of the registration to resolve.
|
1270 | *
|
1271 | * @param {ResolveOptions} resolveOpts
|
1272 | * The resolve options.
|
1273 | *
|
1274 | * @return {any}
|
1275 | * Whatever was resolved.
|
1276 | */
|
1277 | function resolve(name, resolveOpts) {
|
1278 | resolveOpts = resolveOpts || {};
|
1279 | try {
|
1280 | // Grab the registration by name.
|
1281 | var resolver = getRegistration(name);
|
1282 | if (resolutionStack.indexOf(name) > -1) {
|
1283 | throw new AwilixResolutionError(name, resolutionStack, 'Cyclic dependencies detected.');
|
1284 | }
|
1285 | // Used in JSON.stringify.
|
1286 | if (name === 'toJSON') {
|
1287 | return inspectCradle;
|
1288 | }
|
1289 | // Used in console.log.
|
1290 | if (name === 'constructor') {
|
1291 | return createContainer;
|
1292 | }
|
1293 | if (!resolver) {
|
1294 | // Checks for some edge cases.
|
1295 | switch (name) {
|
1296 | // The following checks ensure that console.log on the cradle does not
|
1297 | // throw an error (issue #7).
|
1298 | case 'inspect':
|
1299 | return inspectCradle;
|
1300 | // Edge case: Promise unwrapping will look for a "then" property and attempt to call it.
|
1301 | // Return undefined so that we won't cause a resolution error. (issue #109)
|
1302 | case 'then':
|
1303 | return undefined;
|
1304 | // When using `Array.from` or spreading the cradle, this will
|
1305 | // return the registration names.
|
1306 | case Symbol.iterator:
|
1307 | return cradleIterator;
|
1308 | }
|
1309 | if (resolveOpts.allowUnregistered) {
|
1310 | return undefined;
|
1311 | }
|
1312 | throw new AwilixResolutionError(name, resolutionStack);
|
1313 | }
|
1314 | // Pushes the currently-resolving module name onto the stack
|
1315 | resolutionStack.push(name);
|
1316 | // Do the thing
|
1317 | var cached = void 0;
|
1318 | var resolved = void 0;
|
1319 | switch (resolver.lifetime || Lifetime.TRANSIENT) {
|
1320 | case Lifetime.TRANSIENT:
|
1321 | // Transient lifetime means resolve every time.
|
1322 | resolved = resolver.resolve(container);
|
1323 | break;
|
1324 | case Lifetime.SINGLETON:
|
1325 | // Singleton lifetime means cache at all times, regardless of scope.
|
1326 | cached = rootContainer.cache.get(name);
|
1327 | if (!cached) {
|
1328 | resolved = resolver.resolve(container);
|
1329 | rootContainer.cache.set(name, { resolver: resolver, value: resolved });
|
1330 | }
|
1331 | else {
|
1332 | resolved = cached.value;
|
1333 | }
|
1334 | break;
|
1335 | case Lifetime.SCOPED:
|
1336 | // Scoped lifetime means that the container
|
1337 | // that resolves the registration also caches it.
|
1338 | // When a registration is not found, we travel up
|
1339 | // the family tree until we find one that is cached.
|
1340 | cached = container.cache.get(name);
|
1341 | if (cached !== undefined) {
|
1342 | // We found one!
|
1343 | resolved = cached.value;
|
1344 | break;
|
1345 | }
|
1346 | // If we still have not found one, we need to resolve and cache it.
|
1347 | resolved = resolver.resolve(container);
|
1348 | container.cache.set(name, { resolver: resolver, value: resolved });
|
1349 | break;
|
1350 | default:
|
1351 | throw new AwilixResolutionError(name, resolutionStack, "Unknown lifetime \"" + resolver.lifetime + "\"");
|
1352 | }
|
1353 | // Pop it from the stack again, ready for the next resolution
|
1354 | resolutionStack.pop();
|
1355 | return resolved;
|
1356 | }
|
1357 | catch (err) {
|
1358 | // When we get an error we need to reset the stack.
|
1359 | resolutionStack = [];
|
1360 | throw err;
|
1361 | }
|
1362 | }
|
1363 | /**
|
1364 | * Checks if the registration with the given name exists.
|
1365 | *
|
1366 | * @param {string | symbol} name
|
1367 | * The name of the registration to resolve.
|
1368 | *
|
1369 | * @return {boolean}
|
1370 | * Whether or not the registration exists.
|
1371 | */
|
1372 | function hasRegistration(name) {
|
1373 | return !!getRegistration(name);
|
1374 | }
|
1375 | /**
|
1376 | * Given a registration, class or function, builds it up and returns it.
|
1377 | * Does not cache it, this means that any lifetime configured in case of passing
|
1378 | * a registration will not be used.
|
1379 | *
|
1380 | * @param {Resolver|Class|Function} targetOrResolver
|
1381 | * @param {ResolverOptions} opts
|
1382 | */
|
1383 | function build(targetOrResolver, opts) {
|
1384 | if (targetOrResolver && targetOrResolver.resolve) {
|
1385 | return targetOrResolver.resolve(container);
|
1386 | }
|
1387 | var funcName = 'build';
|
1388 | var paramName = 'targetOrResolver';
|
1389 | AwilixTypeError.assert(targetOrResolver, funcName, paramName, 'a registration, function or class', targetOrResolver);
|
1390 | AwilixTypeError.assert(typeof targetOrResolver === 'function', funcName, paramName, 'a function or class', targetOrResolver);
|
1391 | var resolver = isClass(targetOrResolver)
|
1392 | ? asClass(targetOrResolver, opts)
|
1393 | : asFunction(targetOrResolver, opts);
|
1394 | return resolver.resolve(container);
|
1395 | }
|
1396 | /**
|
1397 | * Disposes this container and it's children, calling the disposer
|
1398 | * on all disposable registrations and clearing the cache.
|
1399 | */
|
1400 | function dispose() {
|
1401 | var entries = Array.from(container.cache.entries());
|
1402 | container.cache.clear();
|
1403 | return Promise.all(entries.map(function (_a) {
|
1404 | _a[0]; var entry = _a[1];
|
1405 | var resolver = entry.resolver, value = entry.value;
|
1406 | var disposable = resolver;
|
1407 | if (disposable.dispose) {
|
1408 | return Promise.resolve().then(function () { return disposable.dispose(value); });
|
1409 | }
|
1410 | return Promise.resolve();
|
1411 | })).then(function () { return undefined; });
|
1412 | }
|
1413 | }
|
1414 |
|
1415 | export { AwilixError, AwilixResolutionError, AwilixTypeError, ExtendableError, InjectionMode, Lifetime, RESOLVER, aliasTo, asClass, asFunction, asValue, createBuildResolver, createContainer, createDisposableResolver };
|