UNPKG

47.9 kBJavaScriptView Raw
1/*! *****************************************************************************
2Copyright (c) Microsoft Corporation.
3
4Permission to use, copy, modify, and/or distribute this software for any
5purpose with or without fee is hereby granted.
6
7THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13PERFORMANCE OF THIS SOFTWARE.
14***************************************************************************** */
15/* global Reflect, Promise */
16
17var 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
24function __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
32var __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
43function __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
71function __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 */
80var EOL = '\n';
81/**
82 * An extendable error class.
83 * @author https://github.com/bjyoungblood/es6-error/
84 */
85var 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 */
112var 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 */
123var 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 */
173var 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 */
212function 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 */
421function 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 */
435function 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()`
447var IDENT_START_EXPR = /^[_$a-zA-Z\xA0-\uFFFF]$/;
448var IDENT_PART_EXPR = /^[._$a-zA-Z0-9\xA0-\uFFFF]$/;
449/**
450 * Determines if the character is a valid JS identifier start character.
451 */
452function isIdentifierStart(ch) {
453 return IDENT_START_EXPR.test(ch);
454}
455/**
456 * Determines if the character is a valid JS identifier start character.
457 */
458function 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 */
473function 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 */
490function 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 */
499function 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 */
527function 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 */
539function uniq(arr) {
540 return Array.from(new Set(arr));
541}
542
543/**
544 * Lifetime types.
545 */
546var 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 */
567var 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>}
589 * Returns an array of parameters.
590 */
591function parseParameterList(source) {
592 var _a = createTokenizer(source), _next = _a.next, done = _a.done;
593 var params = [];
594 var t = null;
595 nextToken();
596 while (!done()) {
597 switch (t.type) {
598 case 'class':
599 skipUntilConstructor();
600 // Next token is the constructor identifier.
601 nextToken();
602 break;
603 case 'function':
604 var next = nextToken();
605 if (next.type === 'ident' || next.type === '*') {
606 // This is the function name or a generator star. Skip it.
607 nextToken();
608 }
609 break;
610 case '(':
611 // Start parsing parameter names.
612 parseParams();
613 break;
614 case ')':
615 // We're now out of the parameter list.
616 return params;
617 case 'ident':
618 // Likely a paren-less arrow function
619 // which can have no default args.
620 var param = { name: t.value, optional: false };
621 if (t.value === 'async') {
622 // Given it's the very first token, we can assume it's an async function,
623 // so skip the async keyword if the next token is not an equals sign, in which
624 // case it is a single-arg arrow func.
625 var next_1 = nextToken();
626 if (next_1 && next_1.type !== '=') {
627 break;
628 }
629 }
630 params.push(param);
631 return params;
632 /* istanbul ignore next */
633 default:
634 throw unexpected();
635 }
636 }
637 return params;
638 /**
639 * After having been placed within the parameter list of
640 * a function, parses the parameters.
641 */
642 function parseParams() {
643 // Current token is a left-paren
644 var param = { name: '', optional: false };
645 while (!done()) {
646 nextToken();
647 switch (t.type) {
648 case 'ident':
649 param.name = t.value;
650 break;
651 case '=':
652 param.optional = true;
653 break;
654 case ',':
655 params.push(param);
656 param = { name: '', optional: false };
657 break;
658 case ')':
659 if (param.name) {
660 params.push(param);
661 }
662 return;
663 /* istanbul ignore next */
664 default:
665 throw unexpected();
666 }
667 }
668 }
669 /**
670 * Skips until we reach the constructor identifier.
671 */
672 function skipUntilConstructor() {
673 while (!isConstructorToken() && !done()) {
674 nextToken(1 /* Dumb */);
675 }
676 }
677 /**
678 * Determines if the current token represents a constructor, and the next token after it is a paren
679 */
680 function isConstructorToken() {
681 return t.type === 'ident' && t.value === 'constructor';
682 }
683 /**
684 * Advances the tokenizer and stores the previous token in history
685 */
686 function nextToken(flags) {
687 if (flags === void 0) { flags = 0 /* None */; }
688 t = _next(flags);
689 return t;
690 }
691 /**
692 * Returns an error describing an unexpected token.
693 */
694 /* istanbul ignore next */
695 function unexpected() {
696 return new SyntaxError("Parsing parameter list, did not expect " + t.type + " token" + (t.value ? " (" + t.value + ")" : ''));
697 }
698}
699
700/**
701 * RESOLVER symbol can be used by modules loaded by
702 * `loadModules` to configure their lifetime, injection mode, etc.
703 */
704var RESOLVER = Symbol('Awilix Resolver Config');
705/**
706 * Creates a simple value resolver where the given value will always be resolved.
707 *
708 * @param {string} name
709 * The name to register the value as.
710 *
711 * @param {*} value
712 * The value to resolve.
713 *
714 * @return {object}
715 * The resolver.
716 */
717function asValue(value) {
718 return {
719 resolve: function () { return value; },
720 };
721}
722/**
723 * Creates a factory resolver, where the given factory function
724 * will be invoked with `new` when requested.
725 *
726 * @param {string} name
727 * The name to register the value as.
728 *
729 * @param {Function} fn
730 * The function to register.
731 *
732 * @param {object} opts
733 * Additional options for the resolver.
734 *
735 * @return {object}
736 * The resolver.
737 */
738function asFunction(fn, opts) {
739 if (!isFunction(fn)) {
740 throw new AwilixTypeError('asFunction', 'fn', 'function', fn);
741 }
742 var defaults = {
743 lifetime: Lifetime.TRANSIENT,
744 };
745 opts = makeOptions(defaults, opts, fn[RESOLVER]);
746 var resolve = generateResolve(fn);
747 var result = __assign({ resolve: resolve }, opts);
748 return createDisposableResolver(createBuildResolver(result));
749}
750/**
751 * Like a factory resolver, but for classes that require `new`.
752 *
753 * @param {string} name
754 * The name to register the value as.
755 *
756 * @param {Class} Type
757 * The function to register.
758 *
759 * @param {object} opts
760 * Additional options for the resolver.
761 *
762 * @return {object}
763 * The resolver.
764 */
765function asClass(Type, opts) {
766 if (!isFunction(Type)) {
767 throw new AwilixTypeError('asClass', 'Type', 'class', Type);
768 }
769 var defaults = {
770 lifetime: Lifetime.TRANSIENT,
771 };
772 opts = makeOptions(defaults, opts, Type[RESOLVER]);
773 // A function to handle object construction for us, as to make the generateResolve more reusable
774 var newClass = function newClass() {
775 return Reflect.construct(Type, arguments);
776 };
777 var resolve = generateResolve(newClass, Type);
778 return createDisposableResolver(createBuildResolver(__assign(__assign({}, opts), { resolve: resolve })));
779}
780/**
781 * Resolves to the specified registration.
782 */
783function aliasTo(name) {
784 return {
785 resolve: function (container) {
786 return container.resolve(name);
787 },
788 };
789}
790/**
791 * Given an options object, creates a fluid interface
792 * to manage it.
793 *
794 * @param {*} obj
795 * The object to return.
796 *
797 * @return {object}
798 * The interface.
799 */
800function createBuildResolver(obj) {
801 function setLifetime(value) {
802 return createBuildResolver(__assign(__assign({}, this), { lifetime: value }));
803 }
804 function setInjectionMode(value) {
805 return createBuildResolver(__assign(__assign({}, this), { injectionMode: value }));
806 }
807 function inject(injector) {
808 return createBuildResolver(__assign(__assign({}, this), { injector: injector }));
809 }
810 return updateResolver(obj, {
811 setLifetime: setLifetime,
812 inject: inject,
813 transient: partial(setLifetime, Lifetime.TRANSIENT),
814 scoped: partial(setLifetime, Lifetime.SCOPED),
815 singleton: partial(setLifetime, Lifetime.SINGLETON),
816 setInjectionMode: setInjectionMode,
817 proxy: partial(setInjectionMode, InjectionMode.PROXY),
818 classic: partial(setInjectionMode, InjectionMode.CLASSIC),
819 });
820}
821/**
822 * Given a resolver, returns an object with methods to manage the disposer
823 * function.
824 * @param obj
825 */
826function createDisposableResolver(obj) {
827 function disposer(dispose) {
828 return createDisposableResolver(__assign(__assign({}, this), { dispose: dispose }));
829 }
830 return updateResolver(obj, {
831 disposer: disposer,
832 });
833}
834/**
835 * Partially apply arguments to the given function.
836 */
837function partial(fn, arg1) {
838 return function partiallyApplied() {
839 return fn.call(this, arg1);
840 };
841}
842/**
843 * Makes an options object based on defaults.
844 *
845 * @param {object} defaults
846 * Default options.
847 *
848 * @param {...} rest
849 * The input to check and possibly assign to the resulting object
850 *
851 * @return {object}
852 */
853function makeOptions(defaults) {
854 var rest = [];
855 for (var _i = 1; _i < arguments.length; _i++) {
856 rest[_i - 1] = arguments[_i];
857 }
858 return Object.assign.apply(Object, __spreadArray([{}, defaults], rest));
859}
860/**
861 * Creates a new resolver with props merged from both.
862 *
863 * @param source
864 * @param target
865 */
866function updateResolver(source, target) {
867 var result = __assign(__assign({}, source), target);
868 return result;
869}
870/**
871 * Returns a wrapped `resolve` function that provides values
872 * from the injector and defers to `container.resolve`.
873 *
874 * @param {AwilixContainer} container
875 * @param {Object} locals
876 * @return {Function}
877 */
878function wrapWithLocals(container, locals) {
879 return function wrappedResolve(name, resolveOpts) {
880 if (name in locals) {
881 return locals[name];
882 }
883 return container.resolve(name, resolveOpts);
884 };
885}
886/**
887 * Returns a new Proxy that checks the result from `injector`
888 * for values before delegating to the actual container.
889 *
890 * @param {Object} cradle
891 * @param {Function} injector
892 * @return {Proxy}
893 */
894function createInjectorProxy(container, injector) {
895 var locals = injector(container);
896 var allKeys = uniq(__spreadArray(__spreadArray([], Reflect.ownKeys(container.cradle)), Reflect.ownKeys(locals)));
897 // TODO: Lots of duplication here from the container proxy.
898 // Need to refactor.
899 var proxy = new Proxy({}, {
900 /**
901 * Resolves the value by first checking the locals, then the container.
902 */
903 get: function (target, name) {
904 if (name === Symbol.iterator) {
905 return function iterateRegistrationsAndLocals() {
906 var _a, _b, _i, prop, _c, _d, _e, prop;
907 return __generator(this, function (_f) {
908 switch (_f.label) {
909 case 0:
910 _a = [];
911 for (_b in container.cradle)
912 _a.push(_b);
913 _i = 0;
914 _f.label = 1;
915 case 1:
916 if (!(_i < _a.length)) return [3 /*break*/, 4];
917 prop = _a[_i];
918 return [4 /*yield*/, prop];
919 case 2:
920 _f.sent();
921 _f.label = 3;
922 case 3:
923 _i++;
924 return [3 /*break*/, 1];
925 case 4:
926 _c = [];
927 for (_d in locals)
928 _c.push(_d);
929 _e = 0;
930 _f.label = 5;
931 case 5:
932 if (!(_e < _c.length)) return [3 /*break*/, 8];
933 prop = _c[_e];
934 return [4 /*yield*/, prop];
935 case 6:
936 _f.sent();
937 _f.label = 7;
938 case 7:
939 _e++;
940 return [3 /*break*/, 5];
941 case 8: return [2 /*return*/];
942 }
943 });
944 };
945 }
946 if (name in locals) {
947 return locals[name];
948 }
949 return container.resolve(name);
950 },
951 /**
952 * Used for `Object.keys`.
953 */
954 ownKeys: function () {
955 return allKeys;
956 },
957 /**
958 * Used for `Object.keys`.
959 */
960 getOwnPropertyDescriptor: function (target, key) {
961 if (allKeys.indexOf(key) > -1) {
962 return {
963 enumerable: true,
964 configurable: true,
965 };
966 }
967 return undefined;
968 },
969 });
970 return proxy;
971}
972/**
973 * Returns a resolve function used to construct the dependency graph
974 *
975 * @this {Registration}
976 * The `this` context is a resolver.
977 *
978 * @param {Function} fn
979 * The function to construct
980 *
981 * @param {Function} dependencyParseTarget
982 * The function to parse for the dependencies of the construction target
983 *
984 * @param {boolean} isFunction
985 * Is the resolution target an actual function or a mask for a constructor?
986 *
987 * @return {Function}
988 * The function used for dependency resolution
989 */
990function generateResolve(fn, dependencyParseTarget) {
991 // If the function used for dependency parsing is falsy, use the supplied function
992 if (!dependencyParseTarget) {
993 dependencyParseTarget = fn;
994 }
995 // Parse out the dependencies
996 // NOTE: we do this regardless of whether PROXY is used or not,
997 // because if this fails, we want it to fail early (at startup) rather
998 // than at resolution time.
999 var dependencies = parseDependencies(dependencyParseTarget);
1000 // Use a regular function instead of an arrow function to facilitate binding to the resolver.
1001 return function resolve(container) {
1002 // Because the container holds a global reolutionMode we need to determine it in the proper order of precedence:
1003 // resolver -> container -> default value
1004 var injectionMode = this.injectionMode ||
1005 container.options.injectionMode ||
1006 InjectionMode.PROXY;
1007 if (injectionMode !== InjectionMode.CLASSIC) {
1008 // If we have a custom injector, we need to wrap the cradle.
1009 var cradle = this.injector
1010 ? createInjectorProxy(container, this.injector)
1011 : container.cradle;
1012 // Return the target injected with the cradle
1013 return fn(cradle);
1014 }
1015 // We have dependencies so we need to resolve them manually
1016 if (dependencies.length > 0) {
1017 var resolve_1 = this.injector
1018 ? wrapWithLocals(container, this.injector(container))
1019 : container.resolve;
1020 var children = dependencies.map(function (p) {
1021 return resolve_1(p.name, { allowUnregistered: p.optional });
1022 });
1023 return fn.apply(void 0, children);
1024 }
1025 return fn();
1026 };
1027}
1028/**
1029 * Parses the dependencies from the given function.
1030 * If it's a class and has an extends clause, and no reported dependencies, attempt to parse it's super constructor.
1031 */
1032function parseDependencies(fn) {
1033 var result = parseParameterList(fn.toString());
1034 if (result.length > 0) {
1035 return result;
1036 }
1037 var parent = Object.getPrototypeOf(fn);
1038 if (typeof parent === 'function' && parent !== Function.prototype) {
1039 // Try to parse the parent
1040 return parseDependencies(parent);
1041 }
1042 return result;
1043}
1044
1045/**
1046 * Family tree symbol.
1047 * @type {Symbol}
1048 */
1049var FAMILY_TREE = Symbol('familyTree');
1050/**
1051 * Roll Up Registrations symbol.
1052 * @type {Symbol}
1053 */
1054var ROLL_UP_REGISTRATIONS = Symbol('rollUpRegistrations');
1055/**
1056 * Creates an Awilix container instance.
1057 *
1058 * @param {Function} options.require
1059 * The require function to use. Defaults to require.
1060 *
1061 * @param {string} options.injectionMode
1062 * The mode used by the container to resolve dependencies. Defaults to 'Proxy'.
1063 *
1064 * @return {object}
1065 * The container.
1066 */
1067function createContainer(options, parentContainer) {
1068 var _a;
1069 options = __assign({ injectionMode: InjectionMode.PROXY }, options);
1070 // The resolution stack is used to keep track
1071 // of what modules are being resolved, so when
1072 // an error occurs, we have something to present
1073 // to the poor developer who fucked up.
1074 var resolutionStack = [];
1075 // For performance reasons, we store
1076 // the rolled-up registrations when starting a resolve.
1077 var computedRegistrations = null;
1078 // Internal registration store for this container.
1079 var registrations = {};
1080 /**
1081 * The `Proxy` that is passed to functions so they can resolve their dependencies without
1082 * knowing where they come from. I call it the "cradle" because
1083 * it is where registered things come to life at resolution-time.
1084 */
1085 var cradle = new Proxy({
1086 /* removed in browser build */
1087 }, {
1088 /**
1089 * The `get` handler is invoked whenever a get-call for `container.cradle.*` is made.
1090 *
1091 * @param {object} target
1092 * The proxy target. Irrelevant.
1093 *
1094 * @param {string} name
1095 * The property name.
1096 *
1097 * @return {*}
1098 * Whatever the resolve call returns.
1099 */
1100 get: function (target, name) { return resolve(name); },
1101 /**
1102 * Setting things on the cradle throws an error.
1103 *
1104 * @param {object} target
1105 * @param {string} name
1106 */
1107 set: function (_target, name, value) {
1108 throw new Error("Attempted setting property \"" + name + "\" on container cradle - this is not allowed.");
1109 },
1110 /**
1111 * Used for `Object.keys`.
1112 */
1113 ownKeys: function () {
1114 return Array.from(cradle);
1115 },
1116 /**
1117 * Used for `Object.keys`.
1118 */
1119 getOwnPropertyDescriptor: function (target, key) {
1120 var regs = rollUpRegistrations();
1121 if (Object.getOwnPropertyDescriptor(regs, key)) {
1122 return {
1123 enumerable: true,
1124 configurable: true,
1125 };
1126 }
1127 return undefined;
1128 },
1129 });
1130 // The container being exposed.
1131 var container = (_a = {
1132 options: options,
1133 cradle: cradle,
1134 inspect: inspect,
1135 cache: new Map(),
1136 loadModules: function () { throw new Error("loadModules is not supported in the browser."); },
1137 createScope: createScope,
1138 register: register,
1139 build: build,
1140 resolve: resolve,
1141 has: has,
1142 dispose: dispose
1143 },
1144 /* removed in browser build */
1145 // tslint:disable-next-line
1146 _a[ROLL_UP_REGISTRATIONS] = rollUpRegistrations,
1147 Object.defineProperty(_a, "registrations", {
1148 get: function () {
1149 return rollUpRegistrations();
1150 },
1151 enumerable: false,
1152 configurable: true
1153 }),
1154 _a);
1155 // Track the family tree.
1156 var familyTree = parentContainer
1157 ? [container].concat(parentContainer[FAMILY_TREE])
1158 : [container];
1159 container[FAMILY_TREE] = familyTree;
1160 // We need a reference to the root container,
1161 // so we can retrieve and store singletons.
1162 var rootContainer = last(familyTree);
1163 return container;
1164 /**
1165 * Used by util.inspect (which is used by console.log).
1166 */
1167 function inspect(depth, opts) {
1168 return "[AwilixContainer (" + (parentContainer ? 'scoped, ' : '') + "registrations: " + Object.keys(container.registrations).length + ")]";
1169 }
1170 /**
1171 * Rolls up registrations from the family tree.
1172 * This is cached until `bustCache` clears it.
1173 *
1174 * @param {boolean} bustCache
1175 * Forces a recomputation.
1176 *
1177 * @return {object}
1178 * The merged registrations object.
1179 */
1180 function rollUpRegistrations(bustCache) {
1181 if (bustCache === void 0) { bustCache = false; }
1182 if (computedRegistrations && !bustCache) {
1183 return computedRegistrations;
1184 }
1185 computedRegistrations = __assign(__assign({}, (parentContainer &&
1186 parentContainer[ROLL_UP_REGISTRATIONS](bustCache))), registrations);
1187 return computedRegistrations;
1188 }
1189 /**
1190 * Used for providing an iterator to the cradle.
1191 */
1192 function registrationNamesIterator() {
1193 var registrations, _a, _b, _i, registrationName;
1194 return __generator(this, function (_c) {
1195 switch (_c.label) {
1196 case 0:
1197 registrations = rollUpRegistrations();
1198 _a = [];
1199 for (_b in registrations)
1200 _a.push(_b);
1201 _i = 0;
1202 _c.label = 1;
1203 case 1:
1204 if (!(_i < _a.length)) return [3 /*break*/, 4];
1205 registrationName = _a[_i];
1206 return [4 /*yield*/, registrationName];
1207 case 2:
1208 _c.sent();
1209 _c.label = 3;
1210 case 3:
1211 _i++;
1212 return [3 /*break*/, 1];
1213 case 4: return [2 /*return*/];
1214 }
1215 });
1216 }
1217 /**
1218 * Creates a scoped container.
1219 *
1220 * @return {object}
1221 * The scoped container.
1222 */
1223 function createScope() {
1224 return createContainer(options, container);
1225 }
1226 /**
1227 * Adds a registration for a resolver.
1228 */
1229 function register(arg1, arg2) {
1230 var obj = nameValueToObject(arg1, arg2);
1231 var keys = __spreadArray(__spreadArray([], Object.keys(obj)), Object.getOwnPropertySymbols(obj));
1232 for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
1233 var key = keys_1[_i];
1234 var value = obj[key];
1235 registrations[key] = value;
1236 }
1237 // Invalidates the computed registrations.
1238 computedRegistrations = null;
1239 return container;
1240 }
1241 /**
1242 * Returned to `util.inspect` when attempting to resolve
1243 * a custom inspector function on the cradle.
1244 */
1245 function inspectCradle() {
1246 return '[AwilixContainer.cradle]';
1247 }
1248 /**
1249 * Resolves the registration with the given name.
1250 *
1251 * @param {string | symbol} name
1252 * The name of the registration to resolve.
1253 *
1254 * @param {ResolveOptions} resolveOpts
1255 * The resolve options.
1256 *
1257 * @return {any}
1258 * Whatever was resolved.
1259 */
1260 function resolve(name, resolveOpts) {
1261 resolveOpts = resolveOpts || {};
1262 if (!resolutionStack.length) {
1263 // Root resolve busts the registration cache.
1264 rollUpRegistrations(true);
1265 }
1266 try {
1267 // Grab the registration by name.
1268 var resolver = computedRegistrations[name];
1269 if (resolutionStack.indexOf(name) > -1) {
1270 throw new AwilixResolutionError(name, resolutionStack, 'Cyclic dependencies detected.');
1271 }
1272 // Used in JSON.stringify.
1273 if (name === 'toJSON') {
1274 return inspectCradle;
1275 }
1276 // Used in console.log.
1277 if (name === 'constructor') {
1278 return createContainer;
1279 }
1280 if (!resolver) {
1281 // The following checks ensure that console.log on the cradle does not
1282 // throw an error (issue #7).
1283 if (name === 'inspect') {
1284 return inspectCradle;
1285 }
1286 // Edge case: Promise unwrapping will look for a "then" property and attempt to call it.
1287 // Return undefined so that we won't cause a resolution error. (issue #109)
1288 if (name === 'then') {
1289 return undefined;
1290 }
1291 // When using `Array.from` or spreading the cradle, this will
1292 // return the registration names.
1293 if (name === Symbol.iterator) {
1294 return registrationNamesIterator;
1295 }
1296 if (resolveOpts.allowUnregistered) {
1297 return undefined;
1298 }
1299 throw new AwilixResolutionError(name, resolutionStack);
1300 }
1301 // Pushes the currently-resolving module name onto the stack
1302 resolutionStack.push(name);
1303 // Do the thing
1304 var cached = void 0;
1305 var resolved = void 0;
1306 switch (resolver.lifetime || Lifetime.TRANSIENT) {
1307 case Lifetime.TRANSIENT:
1308 // Transient lifetime means resolve every time.
1309 resolved = resolver.resolve(container);
1310 break;
1311 case Lifetime.SINGLETON:
1312 // Singleton lifetime means cache at all times, regardless of scope.
1313 cached = rootContainer.cache.get(name);
1314 if (!cached) {
1315 resolved = resolver.resolve(container);
1316 rootContainer.cache.set(name, { resolver: resolver, value: resolved });
1317 }
1318 else {
1319 resolved = cached.value;
1320 }
1321 break;
1322 case Lifetime.SCOPED:
1323 // Scoped lifetime means that the container
1324 // that resolves the registration also caches it.
1325 // When a registration is not found, we travel up
1326 // the family tree until we find one that is cached.
1327 cached = container.cache.get(name);
1328 if (cached !== undefined) {
1329 // We found one!
1330 resolved = cached.value;
1331 break;
1332 }
1333 // If we still have not found one, we need to resolve and cache it.
1334 resolved = resolver.resolve(container);
1335 container.cache.set(name, { resolver: resolver, value: resolved });
1336 break;
1337 default:
1338 throw new AwilixResolutionError(name, resolutionStack, "Unknown lifetime \"" + resolver.lifetime + "\"");
1339 }
1340 // Pop it from the stack again, ready for the next resolution
1341 resolutionStack.pop();
1342 return resolved;
1343 }
1344 catch (err) {
1345 // When we get an error we need to reset the stack.
1346 resolutionStack = [];
1347 throw err;
1348 }
1349 }
1350 /**
1351 * Checks if the registration with the given name exists.
1352 *
1353 * @param {string | symbol} name
1354 * The name of the registration to resolve.
1355 *
1356 * @return {boolean}
1357 * Whether or not the registration exists.
1358 */
1359 function has(name) {
1360 return name in rollUpRegistrations();
1361 }
1362 /**
1363 * Given a registration, class or function, builds it up and returns it.
1364 * Does not cache it, this means that any lifetime configured in case of passing
1365 * a registration will not be used.
1366 *
1367 * @param {Resolver|Class|Function} targetOrResolver
1368 * @param {ResolverOptions} opts
1369 */
1370 function build(targetOrResolver, opts) {
1371 if (targetOrResolver && targetOrResolver.resolve) {
1372 return targetOrResolver.resolve(container);
1373 }
1374 var funcName = 'build';
1375 var paramName = 'targetOrResolver';
1376 AwilixTypeError.assert(targetOrResolver, funcName, paramName, 'a registration, function or class', targetOrResolver);
1377 AwilixTypeError.assert(typeof targetOrResolver === 'function', funcName, paramName, 'a function or class', targetOrResolver);
1378 var resolver = isClass(targetOrResolver)
1379 ? asClass(targetOrResolver, opts)
1380 : asFunction(targetOrResolver, opts);
1381 return resolver.resolve(container);
1382 }
1383 /**
1384 * Disposes this container and it's children, calling the disposer
1385 * on all disposable registrations and clearing the cache.
1386 */
1387 function dispose() {
1388 var entries = Array.from(container.cache.entries());
1389 container.cache.clear();
1390 return Promise.all(entries.map(function (_a) {
1391 _a[0]; var entry = _a[1];
1392 var resolver = entry.resolver, value = entry.value;
1393 var disposable = resolver;
1394 if (disposable.dispose) {
1395 return Promise.resolve().then(function () { return disposable.dispose(value); });
1396 }
1397 return Promise.resolve();
1398 })).then(function () { return undefined; });
1399 }
1400}
1401
1402export { AwilixError, AwilixResolutionError, AwilixTypeError, ExtendableError, InjectionMode, Lifetime, RESOLVER, aliasTo, asClass, asFunction, asValue, createBuildResolver, createContainer, createDisposableResolver };