UNPKG

48.5 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> | null}
589 * Returns an array of parameters, or `null` if no
590 * constructor was found for a class.
591 */
592function 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 */
711var 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 */
724function 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 */
745function 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 */
772function 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 */
790function 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 */
807function 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 */
833function 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 */
844function 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 */
860function 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 */
873function 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 */
885function 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 */
901function 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 */
997function 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 */
1040function 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 */
1058var FAMILY_TREE = Symbol('familyTree');
1059/**
1060 * Roll Up Registrations symbol.
1061 */
1062var 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 */
1075function 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
1415export { AwilixError, AwilixResolutionError, AwilixTypeError, ExtendableError, InjectionMode, Lifetime, RESOLVER, aliasTo, asClass, asFunction, asValue, createBuildResolver, createContainer, createDisposableResolver };