Socket
Socket
Sign inDemoInstall

awilix

Package Overview
Dependencies
Maintainers
1
Versions
90
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

awilix - npm Package Compare versions

Comparing version 11.0.4 to 12.0.0

684

lib/awilix.browser.js

@@ -1,90 +0,8 @@

/******************************************************************************
Copyright (c) Microsoft Corporation.
import * as glob from 'fast-glob';
import * as path from 'path';
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
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;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
/**
* Newline.
*/
var EOL = '\n';
const EOL = '\n';
/**

@@ -94,4 +12,3 @@ * An extendable error class.

*/
var ExtendableError = /** @class */ (function (_super) {
__extends(ExtendableError, _super);
class ExtendableError extends Error {
/**

@@ -103,12 +20,12 @@ * Constructor for the error.

*/
function ExtendableError(message) {
var _this = _super.call(this, message) || this;
constructor(message) {
super(message);
// extending Error is weird and does not propagate `message`
Object.defineProperty(_this, 'message', {
Object.defineProperty(this, 'message', {
enumerable: false,
value: message,
});
Object.defineProperty(_this, 'name', {
Object.defineProperty(this, 'name', {
enumerable: false,
value: _this.constructor.name,
value: this.constructor.name,
});

@@ -118,6 +35,6 @@ // Not all browsers have this function.

if ('captureStackTrace' in Error) {
Error.captureStackTrace(_this, _this.constructor);
Error.captureStackTrace(this, this.constructor);
}
else {
Object.defineProperty(_this, 'stack', {
Object.defineProperty(this, 'stack', {
enumerable: false,

@@ -129,21 +46,13 @@ value: Error(message).stack,

}
return _this;
}
return ExtendableError;
}(Error));
}
/**
* Base error for all Awilix-specific errors.
*/
var AwilixError = /** @class */ (function (_super) {
__extends(AwilixError, _super);
function AwilixError() {
return _super !== null && _super.apply(this, arguments) || this;
}
return AwilixError;
}(ExtendableError));
class AwilixError extends ExtendableError {
}
/**
* Error thrown to indicate a type mismatch.
*/
var AwilixTypeError = /** @class */ (function (_super) {
__extends(AwilixTypeError, _super);
class AwilixTypeError extends AwilixError {
/**

@@ -165,4 +74,4 @@ * Constructor, takes the function name, expected and given

*/
function AwilixTypeError(funcDescription, paramName, expectedType, givenType) {
return _super.call(this, "".concat(funcDescription, ": expected ").concat(paramName, " to be ").concat(expectedType, ", but got ").concat(givenType, ".")) || this;
constructor(funcDescription, paramName, expectedType, givenType) {
super(`${funcDescription}: expected ${paramName} to be ${expectedType}, but got ${givenType}.`);
}

@@ -187,3 +96,3 @@ /**

*/
AwilixTypeError.assert = function (condition, funcDescription, paramName, expectedType, givenType) {
static assert(condition, funcDescription, paramName, expectedType, givenType) {
if (!condition) {

@@ -193,10 +102,8 @@ throw new AwilixTypeError(funcDescription, paramName, expectedType, givenType);

return condition;
};
return AwilixTypeError;
}(AwilixError));
}
}
/**
* A nice error class so we can do an instanceOf check.
*/
var AwilixResolutionError = /** @class */ (function (_super) {
__extends(AwilixResolutionError, _super);
class AwilixResolutionError extends AwilixError {
/**

@@ -212,25 +119,20 @@ * Constructor, takes the registered modules and unresolved tokens

*/
function AwilixResolutionError(name, resolutionStack, message) {
var stringName = name.toString();
var nameStack = resolutionStack.map(function (_a) {
var val = _a.name;
return val.toString();
});
constructor(name, resolutionStack, message) {
const stringName = name.toString();
const nameStack = resolutionStack.map(({ name: val }) => val.toString());
nameStack.push(stringName);
var resolutionPathString = nameStack.join(' -> ');
var msg = "Could not resolve '".concat(stringName, "'.");
const resolutionPathString = nameStack.join(' -> ');
let msg = `Could not resolve '${stringName}'.`;
if (message) {
msg += " ".concat(message);
msg += ` ${message}`;
}
msg += EOL + EOL;
msg += "Resolution path: ".concat(resolutionPathString);
return _super.call(this, msg) || this;
msg += `Resolution path: ${resolutionPathString}`;
super(msg);
}
return AwilixResolutionError;
}(AwilixError));
}
/**
* A nice error class so we can do an instanceOf check.
*/
var AwilixRegistrationError = /** @class */ (function (_super) {
__extends(AwilixRegistrationError, _super);
class AwilixRegistrationError extends AwilixError {
/**

@@ -243,12 +145,11 @@ * Constructor, takes the registered modules and unresolved tokens

*/
function AwilixRegistrationError(name, message) {
var stringName = name.toString();
var msg = "Could not register '".concat(stringName, "'.");
constructor(name, message) {
const stringName = name.toString();
let msg = `Could not register '${stringName}'.`;
if (message) {
msg += " ".concat(message);
msg += ` ${message}`;
}
return _super.call(this, msg) || this;
super(msg);
}
return AwilixRegistrationError;
}(AwilixError));
}

@@ -258,3 +159,3 @@ /**

*/
var InjectionMode = {
const InjectionMode = {
/**

@@ -277,3 +178,3 @@ * The dependencies will be resolved by injecting the cradle proxy.

*/
var Lifetime = {
const Lifetime = {
/**

@@ -309,14 +210,14 @@ * The registration will be resolved once and only once.

function createTokenizer(source) {
var end = source.length;
var pos = 0;
var type = 'EOF';
var value = '';
var flags = 0 /* TokenizerFlags.None */;
const end = source.length;
let pos = 0;
let type = 'EOF';
let value = '';
let flags = 0 /* TokenizerFlags.None */;
// These are used to greedily skip as much as possible.
// Whenever we reach a paren, we increment these.
var parenLeft = 0;
var parenRight = 0;
let parenLeft = 0;
let parenRight = 0;
return {
next: next,
done: done,
next,
done,
};

@@ -326,4 +227,3 @@ /**

*/
function next(nextFlags) {
if (nextFlags === void 0) { nextFlags = 0 /* TokenizerFlags.None */; }
function next(nextFlags = 0 /* TokenizerFlags.None */) {
flags = nextFlags;

@@ -343,3 +243,3 @@ advance();

}
var ch = source.charAt(pos);
const ch = source.charAt(pos);
// Whitespace is irrelevant

@@ -376,10 +276,10 @@ if (isWhiteSpace(ch)) {

pos++;
var nextCh = source.charAt(pos);
const nextCh = source.charAt(pos);
if (nextCh === '/') {
skipUntil(function (c) { return c === '\n'; }, true);
skipUntil((c) => c === '\n', true);
pos++;
}
if (nextCh === '*') {
skipUntil(function (c) {
var closing = source.charAt(pos + 1);
skipUntil((c) => {
const closing = source.charAt(pos + 1);
return c === '*' && closing === '/';

@@ -407,4 +307,4 @@ }, true);

function scanIdentifier() {
var identStart = source.charAt(pos);
var start = ++pos;
const identStart = source.charAt(pos);
const start = ++pos;
while (isIdentifierPart(source.charAt(pos))) {

@@ -425,4 +325,4 @@ pos++;

function skipExpression() {
skipUntil(function (ch) {
var isAtRoot = parenLeft === parenRight + 1;
skipUntil((ch) => {
const isAtRoot = parenLeft === parenRight + 1;
if (ch === ',' && isAtRoot) {

@@ -451,6 +351,5 @@ return true;

*/
function skipUntil(callback, dumb) {
if (dumb === void 0) { dumb = false; }
function skipUntil(callback, dumb = false) {
while (pos < source.length) {
var ch = source.charAt(pos);
const ch = source.charAt(pos);
if (callback(ch)) {

@@ -476,7 +375,7 @@ return;

function skipString() {
var quote = source.charAt(pos);
const quote = source.charAt(pos);
pos++;
while (pos < source.length) {
var ch = source.charAt(pos);
var prev = source.charAt(pos - 1);
const ch = source.charAt(pos);
const prev = source.charAt(pos - 1);
// Checks if the quote was escaped.

@@ -489,5 +388,5 @@ if (ch === quote && prev !== '\\') {

if (quote === '`') {
var next_1 = source.charAt(pos + 1);
if (next_1 === '$') {
var afterDollar = source.charAt(pos + 2);
const next = source.charAt(pos + 1);
if (next === '$') {
const afterDollar = source.charAt(pos + 2);
if (afterDollar === '{') {

@@ -498,3 +397,3 @@ // This is the start of an interpolation; skip the ${

// This includes skipping nested interpolated strings. :D
skipUntil(function (ch) { return ch === '}'; });
skipUntil((ch) => ch === '}');
}

@@ -511,5 +410,5 @@ }

if (value) {
return { value: value, type: type };
return { value, type };
}
return { type: type };
return { type };
}

@@ -555,4 +454,4 @@ /**

// stuff like `MyClass.prototype.constructor()`
var IDENT_START_EXPR = /^[_$a-zA-Z\xA0-\uFFFF]$/;
var IDENT_PART_EXPR = /^[._$a-zA-Z0-9\xA0-\uFFFF]$/;
const IDENT_START_EXPR = /^[_$a-zA-Z\xA0-\uFFFF]$/;
const IDENT_PART_EXPR = /^[._$a-zA-Z0-9\xA0-\uFFFF]$/;
/**

@@ -572,2 +471,20 @@ * Determines if the character is a valid JS identifier start character.

/**
* Quick flatten utility to flatten a 2-dimensional array.
*
* @param {Array<Array<Item>>} array
* The array to flatten.
*
* @return {Array<Item>}
* The flattened array.
*/
function flatten(array) {
const result = [];
array.forEach((arr) => {
arr.forEach((item) => {
result.push(item);
});
});
return result;
}
/**
* Creates a { name: value } object if the input isn't already in that format.

@@ -584,6 +501,5 @@ *

function nameValueToObject(name, value) {
var _a;
var obj = name;
const obj = name;
if (typeof obj === 'string' || typeof obj === 'symbol') {
return _a = {}, _a[name] = value, _a;
return { [name]: value };
}

@@ -617,8 +533,8 @@ return obj;

// Should only need 2 tokens.
var tokenizer = createTokenizer(fn.toString());
var first = tokenizer.next();
const tokenizer = createTokenizer(fn.toString());
const first = tokenizer.next();
if (first.type === 'class') {
return true;
}
var second = tokenizer.next();
const second = tokenizer.next();
if (first.type === 'function' && second.value) {

@@ -640,2 +556,3 @@ if (second.value[0] === second.value[0].toUpperCase()) {

*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
function isFunction(val) {

@@ -657,2 +574,58 @@ return typeof val === 'function';

// Regex to extract the module name.
const nameExpr = /(.*)\..*/i;
/**
* Internal method for globbing a single pattern.
*
* @param {String} globPattern
* The glob pattern.
*
* @param {String} opts.cwd
* Current working directory, used for resolving filepaths.
* Defaults to `process.cwd()`.
*
* @return {[{name, path, opts}]}
* The module names and paths.
*
* @api private
*/
function _listModules(globPattern, opts) {
opts = { cwd: process.cwd(), glob: glob.sync, ...opts };
let patternOpts = null;
if (Array.isArray(globPattern)) {
patternOpts = globPattern[1];
globPattern = globPattern[0];
}
// Replace Windows path separators with Posix path
globPattern = globPattern.replace(/\\/g, '/');
const result = opts.glob(globPattern, { cwd: opts.cwd });
const mapped = result.map((p) => ({
name: nameExpr.exec(path.basename(p))[1],
path: path.resolve(opts.cwd, p),
opts: patternOpts,
}));
return mapped;
}
/**
* Returns a list of {name, path} pairs,
* where the name is the module name, and path is the actual
* full path to the module.
*
* @param {String|Array<String>} globPatterns
* The glob pattern as a string or an array of strings.
*
* @param {String} opts.cwd
* Current working directory, used for resolving filepaths.
* Defaults to `process.cwd()`.
*
* @return {[{name, path}]}
* An array of objects with the module names and paths.
*/
function listModules(globPatterns, opts) {
if (Array.isArray(globPatterns)) {
return flatten(globPatterns.map((p) => _listModules(p, opts)));
}
return _listModules(globPatterns, opts);
}
/*

@@ -669,5 +642,5 @@ * Parses the parameter list of a function string, including ES6 class constructors.

function parseParameterList(source) {
var _a = createTokenizer(source), _next = _a.next, done = _a.done;
var params = [];
var t = null;
const { next: _next, done } = createTokenizer(source);
const params = [];
let t = null;
nextToken();

@@ -687,3 +660,3 @@ while (!done()) {

case 'function': {
var next = nextToken();
const next = nextToken();
if (next.type === 'ident' || next.type === '*') {

@@ -705,3 +678,3 @@ // This is the function name or a generator star. Skip it.

// which can have no default args.
var param = { name: t.value, optional: false };
const param = { name: t.value, optional: false };
if (t.value === 'async') {

@@ -711,3 +684,3 @@ // Given it's the very first token, we can assume it's an async function,

// case it is a single-arg arrow func.
var next = nextToken();
const next = nextToken();
if (next && next.type !== '=') {

@@ -732,3 +705,3 @@ break;

// Current token is a left-paren
var param = { name: '', optional: false };
let param = { name: '', optional: false };
while (!done()) {

@@ -776,4 +749,3 @@ nextToken();

*/
function nextToken(flags) {
if (flags === void 0) { flags = 0 /* TokenizerFlags.None */; }
function nextToken(flags = 0 /* TokenizerFlags.None */) {
t = _next(flags);

@@ -787,3 +759,3 @@ return t;

function unexpected() {
return new SyntaxError("Parsing parameter list, did not expect ".concat(t.type, " token").concat(t.value ? " (".concat(t.value, ")") : ''));
return new SyntaxError(`Parsing parameter list, did not expect ${t.type} token${t.value ? ` (${t.value})` : ''}`);
}

@@ -798,3 +770,3 @@ }

*/
var RESOLVER = Symbol('Awilix Resolver Config');
const RESOLVER = Symbol('Awilix Resolver Config');
/**

@@ -813,3 +785,3 @@ * Creates a simple value resolver where the given value will always be resolved. The value is

return {
resolve: function () { return value; },
resolve: () => value,
isLeakSafe: true,

@@ -838,8 +810,11 @@ };

}
var defaults = {
const defaults = {
lifetime: Lifetime.TRANSIENT,
};
opts = makeOptions(defaults, opts, fn[RESOLVER]);
var resolve = generateResolve(fn);
var result = __assign({ resolve: resolve }, opts);
const resolve = generateResolve(fn);
const result = {
resolve,
...opts,
};
return createDisposableResolver(createBuildResolver(result));

@@ -866,3 +841,3 @@ }

}
var defaults = {
const defaults = {
lifetime: Lifetime.TRANSIENT,

@@ -872,11 +847,10 @@ };

// A function to handle object construction for us, as to make the generateResolve more reusable
var newClass = function newClass() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
const newClass = function newClass(...args) {
return Reflect.construct(Type, args);
};
var resolve = generateResolve(newClass, Type);
return createDisposableResolver(createBuildResolver(__assign(__assign({}, opts), { resolve: resolve })));
const resolve = generateResolve(newClass, Type);
return createDisposableResolver(createBuildResolver({
...opts,
resolve,
}));
}

@@ -889,3 +863,3 @@ /**

return {
resolve: function (container) {
resolve(container) {
return container.resolve(name);

@@ -908,17 +882,26 @@ },

function setLifetime(value) {
return createBuildResolver(__assign(__assign({}, this), { lifetime: value }));
return createBuildResolver({
...this,
lifetime: value,
});
}
function setInjectionMode(value) {
return createBuildResolver(__assign(__assign({}, this), { injectionMode: value }));
return createBuildResolver({
...this,
injectionMode: value,
});
}
function inject(injector) {
return createBuildResolver(__assign(__assign({}, this), { injector: injector }));
return createBuildResolver({
...this,
injector,
});
}
return updateResolver(obj, {
setLifetime: setLifetime,
inject: inject,
setLifetime,
inject,
transient: partial(setLifetime, Lifetime.TRANSIENT),
scoped: partial(setLifetime, Lifetime.SCOPED),
singleton: partial(setLifetime, Lifetime.SINGLETON),
setInjectionMode: setInjectionMode,
setInjectionMode,
proxy: partial(setInjectionMode, InjectionMode.PROXY),

@@ -935,6 +918,9 @@ classic: partial(setInjectionMode, InjectionMode.CLASSIC),

function disposer(dispose) {
return createDisposableResolver(__assign(__assign({}, this), { dispose: dispose }));
return createDisposableResolver({
...this,
dispose,
});
}
return updateResolver(obj, {
disposer: disposer,
disposer,
});

@@ -961,8 +947,4 @@ }

*/
function makeOptions(defaults) {
var rest = [];
for (var _i = 1; _i < arguments.length; _i++) {
rest[_i - 1] = arguments[_i];
}
return Object.assign.apply(Object, __spreadArray([{}, defaults], rest, false));
function makeOptions(defaults, ...rest) {
return Object.assign({}, defaults, ...rest);
}

@@ -976,3 +958,6 @@ /**

function updateResolver(source, target) {
var result = __assign(__assign({}, source), target);
const result = {
...source,
...target,
};
return result;

@@ -1005,57 +990,22 @@ }

function createInjectorProxy(container, injector) {
var locals = injector(container);
var allKeys = uniq(__spreadArray(__spreadArray([], Reflect.ownKeys(container.cradle), true), Reflect.ownKeys(locals), true));
const locals = injector(container);
const allKeys = uniq([
...Reflect.ownKeys(container.cradle),
...Reflect.ownKeys(locals),
]);
// TODO: Lots of duplication here from the container proxy.
// Need to refactor.
var proxy = new Proxy({}, {
const proxy = new Proxy({}, {
/**
* Resolves the value by first checking the locals, then the container.
*/
get: function (target, name) {
get(target, name) {
if (name === Symbol.iterator) {
return function iterateRegistrationsAndLocals() {
var _a, _b, _c, _i, prop, _d, _e, _f, _g, prop;
return __generator(this, function (_h) {
switch (_h.label) {
case 0:
_a = container.cradle;
_b = [];
for (_c in _a)
_b.push(_c);
_i = 0;
_h.label = 1;
case 1:
if (!(_i < _b.length)) return [3 /*break*/, 4];
_c = _b[_i];
if (!(_c in _a)) return [3 /*break*/, 3];
prop = _c;
return [4 /*yield*/, prop];
case 2:
_h.sent();
_h.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4:
_d = locals;
_e = [];
for (_f in _d)
_e.push(_f);
_g = 0;
_h.label = 5;
case 5:
if (!(_g < _e.length)) return [3 /*break*/, 8];
_f = _e[_g];
if (!(_f in _d)) return [3 /*break*/, 7];
prop = _f;
return [4 /*yield*/, prop];
case 6:
_h.sent();
_h.label = 7;
case 7:
_g++;
return [3 /*break*/, 5];
case 8: return [2 /*return*/];
}
});
return function* iterateRegistrationsAndLocals() {
for (const prop in container.cradle) {
yield prop;
}
for (const prop in locals) {
yield prop;
}
};

@@ -1071,3 +1021,3 @@ }

*/
ownKeys: function () {
ownKeys() {
return allKeys;

@@ -1078,3 +1028,3 @@ },

*/
getOwnPropertyDescriptor: function (target, key) {
getOwnPropertyDescriptor(target, key) {
if (allKeys.indexOf(key) > -1) {

@@ -1118,3 +1068,3 @@ return {

// than at resolution time.
var dependencies = parseDependencies(dependencyParseTarget);
const dependencies = parseDependencies(dependencyParseTarget);
// Use a regular function instead of an arrow function to facilitate binding to the resolver.

@@ -1124,3 +1074,3 @@ return function resolve(container) {

// resolver -> container -> default value
var injectionMode = this.injectionMode ||
const injectionMode = this.injectionMode ||
container.options.injectionMode ||

@@ -1130,3 +1080,3 @@ InjectionMode.PROXY;

// If we have a custom injector, we need to wrap the cradle.
var cradle = this.injector
const cradle = this.injector
? createInjectorProxy(container, this.injector)

@@ -1139,9 +1089,7 @@ : container.cradle;

if (dependencies.length > 0) {
var resolve_1 = this.injector
const resolve = this.injector
? wrapWithLocals(container, this.injector(container))
: container.resolve;
var children = dependencies.map(function (p) {
return resolve_1(p.name, { allowUnregistered: p.optional });
});
return fn.apply(void 0, children);
const children = dependencies.map((p) => resolve(p.name, { allowUnregistered: p.optional }));
return fn(...children);
}

@@ -1157,7 +1105,7 @@ return fn();

function parseDependencies(fn) {
var result = parseParameterList(fn.toString());
const result = parseParameterList(fn.toString());
if (!result) {
// No defined constructor for a class, check if there is a parent
// we can parse.
var parent = Object.getPrototypeOf(fn);
const parent = Object.getPrototypeOf(fn);
if (typeof parent === 'function' && parent !== Function.prototype) {

@@ -1175,11 +1123,11 @@ // Try to parse the parent

*/
var FAMILY_TREE = Symbol('familyTree');
const FAMILY_TREE = Symbol('familyTree');
/**
* Roll Up Registrations symbol.
*/
var ROLL_UP_REGISTRATIONS = Symbol('rollUpRegistrations');
const ROLL_UP_REGISTRATIONS = Symbol('rollUpRegistrations');
/**
* The string representation when calling toString.
*/
var CRADLE_STRING_TAG = 'AwilixContainerCradle';
const CRADLE_STRING_TAG = 'AwilixContainerCradle';
/**

@@ -1198,9 +1146,11 @@ * Creates an Awilix container instance.

*/
function createContainer(options) {
if (options === void 0) { options = {}; }
function createContainer(options = {}) {
return createContainerInternal(options);
}
function createContainerInternal(options, parentContainer, parentResolutionStack) {
var _a;
options = __assign({ injectionMode: InjectionMode.PROXY, strict: false }, options);
options = {
injectionMode: InjectionMode.PROXY,
strict: false,
...options,
};
/**

@@ -1210,5 +1160,5 @@ * Tracks the names and lifetimes of the modules being resolved. Used to detect circular

*/
var resolutionStack = parentResolutionStack !== null && parentResolutionStack !== void 0 ? parentResolutionStack : [];
const resolutionStack = parentResolutionStack ?? [];
// Internal registration store for this container.
var registrations = {};
const registrations = {};
/**

@@ -1219,3 +1169,3 @@ * The `Proxy` that is passed to functions so they can resolve their dependencies without

*/
var cradle = new Proxy({
const cradle = new Proxy({
/* removed in browser build */

@@ -1235,3 +1185,3 @@ }, {

*/
get: function (_target, name) { return resolve(name); },
get: (_target, name) => resolve(name),
/**

@@ -1243,4 +1193,4 @@ * Setting things on the cradle throws an error.

*/
set: function (_target, name) {
throw new Error("Attempted setting property \"".concat(name, "\" on container cradle - this is not allowed."));
set: (_target, name) => {
throw new Error(`Attempted setting property "${name}" on container cradle - this is not allowed.`);
},

@@ -1250,3 +1200,3 @@ /**

*/
ownKeys: function () {
ownKeys() {
return Array.from(cradle);

@@ -1257,4 +1207,4 @@ },

*/
getOwnPropertyDescriptor: function (target, key) {
var regs = rollUpRegistrations();
getOwnPropertyDescriptor(target, key) {
const regs = rollUpRegistrations();
if (Object.getOwnPropertyDescriptor(regs, key)) {

@@ -1270,28 +1220,23 @@ return {

// The container being exposed.
var container = (_a = {
options: options,
cradle: cradle,
inspect: inspect,
cache: new Map(),
loadModules: function () { throw new Error("loadModules is not supported in the browser."); },
createScope: createScope,
register: register,
build: build,
resolve: resolve,
hasRegistration: hasRegistration,
dispose: dispose,
getRegistration: getRegistration
const container = {
options,
cradle,
inspect,
cache: new Map(),
loadModules: () => { throw new Error("loadModules is not supported in the browser."); },
createScope,
register: register,
build,
resolve,
hasRegistration,
dispose,
getRegistration,
/* removed in browser build */
[ROLL_UP_REGISTRATIONS]: rollUpRegistrations,
get registrations() {
return rollUpRegistrations();
},
/* removed in browser build */
_a[ROLL_UP_REGISTRATIONS] = rollUpRegistrations,
Object.defineProperty(_a, "registrations", {
get: function () {
return rollUpRegistrations();
},
enumerable: false,
configurable: true
}),
_a);
};
// Track the family tree.
var familyTree = parentContainer
const familyTree = parentContainer
? [container].concat(parentContainer[FAMILY_TREE])

@@ -1302,3 +1247,3 @@ : [container];

// so we can retrieve and store singletons.
var rootContainer = last(familyTree);
const rootContainer = last(familyTree);
return container;

@@ -1309,3 +1254,3 @@ /**

function inspect() {
return "[AwilixContainer (".concat(parentContainer ? 'scoped, ' : '', "registrations: ").concat(Object.keys(container.registrations).length, ")]");
return `[AwilixContainer (${parentContainer ? 'scoped, ' : ''}registrations: ${Object.keys(container.registrations).length})]`;
}

@@ -1326,3 +1271,6 @@ /**

function rollUpRegistrations() {
return __assign(__assign({}, (parentContainer && parentContainer[ROLL_UP_REGISTRATIONS]())), registrations);
return {
...(parentContainer && parentContainer[ROLL_UP_REGISTRATIONS]()),
...registrations,
};
}

@@ -1332,29 +1280,7 @@ /**

*/
function cradleIterator() {
var registrations, _a, _b, _c, _i, registrationName;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
registrations = rollUpRegistrations();
_a = registrations;
_b = [];
for (_c in _a)
_b.push(_c);
_i = 0;
_d.label = 1;
case 1:
if (!(_i < _b.length)) return [3 /*break*/, 4];
_c = _b[_i];
if (!(_c in _a)) return [3 /*break*/, 3];
registrationName = _c;
return [4 /*yield*/, registrationName];
case 2:
_d.sent();
_d.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
function* cradleIterator() {
const registrations = rollUpRegistrations();
for (const registrationName in registrations) {
yield registrationName;
}
}

@@ -1374,7 +1300,6 @@ /**

function register(arg1, arg2) {
var obj = nameValueToObject(arg1, arg2);
var keys = __spreadArray(__spreadArray([], Object.keys(obj), true), Object.getOwnPropertySymbols(obj), true);
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
var resolver = obj[key];
const obj = nameValueToObject(arg1, arg2);
const keys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
for (const key of keys) {
const resolver = obj[key];
// If strict mode is enabled, check to ensure we are not registering a singleton on a non-root

@@ -1405,3 +1330,3 @@ // container.

function getRegistration(name) {
var resolver = registrations[name];
const resolver = registrations[name];
if (resolver) {

@@ -1431,7 +1356,4 @@ return resolver;

// Grab the registration by name.
var resolver = getRegistration(name);
if (resolutionStack.some(function (_a) {
var parentName = _a.name;
return parentName === name;
})) {
const resolver = getRegistration(name);
if (resolutionStack.some(({ name: parentName }) => parentName === name)) {
throw new AwilixResolutionError(name, resolutionStack, 'Cyclic dependencies detected.');

@@ -1471,20 +1393,17 @@ }

}
var lifetime_1 = resolver.lifetime || Lifetime.TRANSIENT;
const lifetime = resolver.lifetime || Lifetime.TRANSIENT;
// if we are running in strict mode, this resolver is not explicitly marked leak-safe, and any
// of the parents have a shorter lifetime than the one requested, throw an error.
if (options.strict && !resolver.isLeakSafe) {
var maybeLongerLifetimeParentIndex = resolutionStack.findIndex(function (_a) {
var parentLifetime = _a.lifetime;
return isLifetimeLonger(parentLifetime, lifetime_1);
});
const maybeLongerLifetimeParentIndex = resolutionStack.findIndex(({ lifetime: parentLifetime }) => isLifetimeLonger(parentLifetime, lifetime));
if (maybeLongerLifetimeParentIndex > -1) {
throw new AwilixResolutionError(name, resolutionStack, "Dependency '".concat(name.toString(), "' has a shorter lifetime than its ancestor: '").concat(resolutionStack[maybeLongerLifetimeParentIndex].name.toString(), "'"));
throw new AwilixResolutionError(name, resolutionStack, `Dependency '${name.toString()}' has a shorter lifetime than its ancestor: '${resolutionStack[maybeLongerLifetimeParentIndex].name.toString()}'`);
}
}
// Pushes the currently-resolving module information onto the stack
resolutionStack.push({ name: name, lifetime: lifetime_1 });
resolutionStack.push({ name, lifetime });
// Do the thing
var cached = void 0;
var resolved = void 0;
switch (lifetime_1) {
let cached;
let resolved;
switch (lifetime) {
case Lifetime.TRANSIENT:

@@ -1501,3 +1420,3 @@ // Transient lifetime means resolve every time.

resolved = resolver.resolve(options.strict ? rootContainer : container);
rootContainer.cache.set(name, { resolver: resolver, value: resolved });
rootContainer.cache.set(name, { resolver, value: resolved });
}

@@ -1522,6 +1441,6 @@ else {

resolved = resolver.resolve(container);
container.cache.set(name, { resolver: resolver, value: resolved });
container.cache.set(name, { resolver, value: resolved });
break;
default:
throw new AwilixResolutionError(name, resolutionStack, "Unknown lifetime \"".concat(resolver.lifetime, "\""));
throw new AwilixResolutionError(name, resolutionStack, `Unknown lifetime "${resolver.lifetime}"`);
}

@@ -1563,7 +1482,7 @@ // Pop it from the stack again, ready for the next resolution

}
var funcName = 'build';
var paramName = 'targetOrResolver';
const funcName = 'build';
const paramName = 'targetOrResolver';
AwilixTypeError.assert(targetOrResolver, funcName, paramName, 'a registration, function or class', targetOrResolver);
AwilixTypeError.assert(typeof targetOrResolver === 'function', funcName, paramName, 'a function or class', targetOrResolver);
var resolver = isClass(targetOrResolver)
const resolver = isClass(targetOrResolver)
? asClass(targetOrResolver, opts)

@@ -1578,16 +1497,15 @@ : asFunction(targetOrResolver, opts);

function dispose() {
var entries = Array.from(container.cache.entries());
const entries = Array.from(container.cache.entries());
container.cache.clear();
return Promise.all(entries.map(function (_a) {
var entry = _a[1];
var resolver = entry.resolver, value = entry.value;
var disposable = resolver;
return Promise.all(entries.map(([, entry]) => {
const { resolver, value } = entry;
const disposable = resolver;
if (disposable.dispose) {
return Promise.resolve().then(function () { return disposable.dispose(value); });
return Promise.resolve().then(() => disposable.dispose(value));
}
return Promise.resolve();
})).then(function () { return undefined; });
})).then(() => undefined);
}
}
export { AwilixError, AwilixRegistrationError, AwilixResolutionError, AwilixTypeError, InjectionMode, Lifetime, RESOLVER, aliasTo, asClass, asFunction, asValue, createBuildResolver, createContainer, createDisposableResolver };
export { AwilixError, AwilixRegistrationError, AwilixResolutionError, AwilixTypeError, InjectionMode, Lifetime, RESOLVER, aliasTo, asClass, asFunction, asValue, createBuildResolver, createContainer, createDisposableResolver, isClass, isFunction, listModules };

@@ -1,6 +0,7 @@

export { AwilixContainer, ContainerOptions, createContainer, CacheEntry, ClassOrFunctionReturning, FunctionReturning, NameAndRegistrationPair, RegistrationHash, ResolveOptions, } from './container';
export { type AwilixContainer, type ContainerOptions, type CacheEntry, type ClassOrFunctionReturning, type FunctionReturning, type NameAndRegistrationPair, type RegistrationHash, type ResolveOptions, createContainer, } from './container';
export { AwilixError, AwilixRegistrationError, AwilixResolutionError, AwilixTypeError, } from './errors';
export { InjectionMode, InjectionModeType } from './injection-mode';
export { Lifetime, LifetimeType } from './lifetime';
export { GlobWithOptions, ListModulesOptions, ModuleDescriptor, listModules, } from './list-modules';
export { BuildResolverOptions, Disposer, InjectorFunction, Resolver, ResolverOptions, BuildResolver, Constructor, DisposableResolver, DisposableResolverOptions, RESOLVER, aliasTo, asClass, asFunction, asValue, createBuildResolver, createDisposableResolver, } from './resolvers';
export { InjectionMode, type InjectionModeType } from './injection-mode';
export { Lifetime, type LifetimeType } from './lifetime';
export { type GlobWithOptions, type ListModulesOptions, type ModuleDescriptor, listModules, } from './list-modules';
export { type BuildResolverOptions, type Disposer, type InjectorFunction, type Resolver, type ResolverOptions, type BuildResolver, type Constructor, type DisposableResolver, type DisposableResolverOptions, RESOLVER, aliasTo, asClass, asFunction, asValue, createBuildResolver, createDisposableResolver, } from './resolvers';
export { isClass, isFunction } from './utils';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createDisposableResolver = exports.createBuildResolver = exports.asValue = exports.asFunction = exports.asClass = exports.aliasTo = exports.RESOLVER = exports.listModules = exports.Lifetime = exports.InjectionMode = exports.AwilixTypeError = exports.AwilixResolutionError = exports.AwilixRegistrationError = exports.AwilixError = exports.createContainer = void 0;
exports.isFunction = exports.isClass = exports.createDisposableResolver = exports.createBuildResolver = exports.asValue = exports.asFunction = exports.asClass = exports.aliasTo = exports.RESOLVER = exports.listModules = exports.Lifetime = exports.InjectionMode = exports.AwilixTypeError = exports.AwilixResolutionError = exports.AwilixRegistrationError = exports.AwilixError = exports.createContainer = void 0;
var container_1 = require("./container");

@@ -25,2 +25,5 @@ Object.defineProperty(exports, "createContainer", { enumerable: true, get: function () { return container_1.createContainer; } });

Object.defineProperty(exports, "createDisposableResolver", { enumerable: true, get: function () { return resolvers_1.createDisposableResolver; } });
var utils_1 = require("./utils");
Object.defineProperty(exports, "isClass", { enumerable: true, get: function () { return utils_1.isClass; } });
Object.defineProperty(exports, "isFunction", { enumerable: true, get: function () { return utils_1.isFunction; } });
//# sourceMappingURL=awilix.js.map
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Awilix = {}));
})(this, (function (exports) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('fast-glob'), require('path')) :
typeof define === 'function' && define.amd ? define(['exports', 'fast-glob', 'path'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Awilix = {}, global.glob, global.path));
})(this, (function (exports, glob, path) { 'use strict';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
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;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
var glob__namespace = /*#__PURE__*/_interopNamespaceDefault(glob);
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
/**
* Newline.
*/
const EOL = '\n';
/**
* An extendable error class.
* @author https://github.com/bjyoungblood/es6-error/
*/
class ExtendableError extends Error {
/**
* Constructor for the error.
*
* @param {String} message
* The error message.
*/
constructor(message) {
super(message);
// extending Error is weird and does not propagate `message`
Object.defineProperty(this, 'message', {
enumerable: false,
value: message,
});
Object.defineProperty(this, 'name', {
enumerable: false,
value: this.constructor.name,
});
// Not all browsers have this function.
/* istanbul ignore else */
if ('captureStackTrace' in Error) {
Error.captureStackTrace(this, this.constructor);
}
else {
Object.defineProperty(this, 'stack', {
enumerable: false,
value: Error(message).stack,
writable: true,
configurable: true,
});
}
}
}
/**
* Base error for all Awilix-specific errors.
*/
class AwilixError extends ExtendableError {
}
/**
* Error thrown to indicate a type mismatch.
*/
class AwilixTypeError extends AwilixError {
/**
* Constructor, takes the function name, expected and given
* type to produce an error.
*
* @param {string} funcDescription
* Name of the function being guarded.
*
* @param {string} paramName
* The parameter there was an issue with.
*
* @param {string} expectedType
* Name of the expected type.
*
* @param {string} givenType
* Name of the given type.
*/
constructor(funcDescription, paramName, expectedType, givenType) {
super(`${funcDescription}: expected ${paramName} to be ${expectedType}, but got ${givenType}.`);
}
/**
* Asserts the given condition, throws an error otherwise.
*
* @param {*} condition
* The condition to check
*
* @param {string} funcDescription
* Name of the function being guarded.
*
* @param {string} paramName
* The parameter there was an issue with.
*
* @param {string} expectedType
* Name of the expected type.
*
* @param {string} givenType
* Name of the given type.
*/
static assert(condition, funcDescription, paramName, expectedType, givenType) {
if (!condition) {
throw new AwilixTypeError(funcDescription, paramName, expectedType, givenType);
}
return condition;
}
}
/**
* A nice error class so we can do an instanceOf check.
*/
class AwilixResolutionError extends AwilixError {
/**
* Constructor, takes the registered modules and unresolved tokens
* to create a message.
*
* @param {string|symbol} name
* The name of the module that could not be resolved.
*
* @param {string[]} resolutionStack
* The current resolution stack
*/
constructor(name, resolutionStack, message) {
const stringName = name.toString();
const nameStack = resolutionStack.map(({ name: val }) => val.toString());
nameStack.push(stringName);
const resolutionPathString = nameStack.join(' -> ');
let msg = `Could not resolve '${stringName}'.`;
if (message) {
msg += ` ${message}`;
}
msg += EOL + EOL;
msg += `Resolution path: ${resolutionPathString}`;
super(msg);
}
}
/**
* A nice error class so we can do an instanceOf check.
*/
class AwilixRegistrationError extends AwilixError {
/**
* Constructor, takes the registered modules and unresolved tokens
* to create a message.
*
* @param {string|symbol} name
* The name of the module that could not be registered.
*/
constructor(name, message) {
const stringName = name.toString();
let msg = `Could not register '${stringName}'.`;
if (message) {
msg += ` ${message}`;
}
super(msg);
}
}
/**
* Newline.
*/
var EOL = '\n';
/**
* An extendable error class.
* @author https://github.com/bjyoungblood/es6-error/
*/
var ExtendableError = /** @class */ (function (_super) {
__extends(ExtendableError, _super);
/**
* Constructor for the error.
*
* @param {String} message
* The error message.
*/
function ExtendableError(message) {
var _this = _super.call(this, message) || this;
// extending Error is weird and does not propagate `message`
Object.defineProperty(_this, 'message', {
enumerable: false,
value: message,
});
Object.defineProperty(_this, 'name', {
enumerable: false,
value: _this.constructor.name,
});
// Not all browsers have this function.
/* istanbul ignore else */
if ('captureStackTrace' in Error) {
Error.captureStackTrace(_this, _this.constructor);
}
else {
Object.defineProperty(_this, 'stack', {
enumerable: false,
value: Error(message).stack,
writable: true,
configurable: true,
});
}
return _this;
}
return ExtendableError;
}(Error));
/**
* Base error for all Awilix-specific errors.
*/
var AwilixError = /** @class */ (function (_super) {
__extends(AwilixError, _super);
function AwilixError() {
return _super !== null && _super.apply(this, arguments) || this;
}
return AwilixError;
}(ExtendableError));
/**
* Error thrown to indicate a type mismatch.
*/
var AwilixTypeError = /** @class */ (function (_super) {
__extends(AwilixTypeError, _super);
/**
* Constructor, takes the function name, expected and given
* type to produce an error.
*
* @param {string} funcDescription
* Name of the function being guarded.
*
* @param {string} paramName
* The parameter there was an issue with.
*
* @param {string} expectedType
* Name of the expected type.
*
* @param {string} givenType
* Name of the given type.
*/
function AwilixTypeError(funcDescription, paramName, expectedType, givenType) {
return _super.call(this, "".concat(funcDescription, ": expected ").concat(paramName, " to be ").concat(expectedType, ", but got ").concat(givenType, ".")) || this;
}
/**
* Asserts the given condition, throws an error otherwise.
*
* @param {*} condition
* The condition to check
*
* @param {string} funcDescription
* Name of the function being guarded.
*
* @param {string} paramName
* The parameter there was an issue with.
*
* @param {string} expectedType
* Name of the expected type.
*
* @param {string} givenType
* Name of the given type.
*/
AwilixTypeError.assert = function (condition, funcDescription, paramName, expectedType, givenType) {
if (!condition) {
throw new AwilixTypeError(funcDescription, paramName, expectedType, givenType);
}
return condition;
};
return AwilixTypeError;
}(AwilixError));
/**
* A nice error class so we can do an instanceOf check.
*/
var AwilixResolutionError = /** @class */ (function (_super) {
__extends(AwilixResolutionError, _super);
/**
* Constructor, takes the registered modules and unresolved tokens
* to create a message.
*
* @param {string|symbol} name
* The name of the module that could not be resolved.
*
* @param {string[]} resolutionStack
* The current resolution stack
*/
function AwilixResolutionError(name, resolutionStack, message) {
var stringName = name.toString();
var nameStack = resolutionStack.map(function (_a) {
var val = _a.name;
return val.toString();
});
nameStack.push(stringName);
var resolutionPathString = nameStack.join(' -> ');
var msg = "Could not resolve '".concat(stringName, "'.");
if (message) {
msg += " ".concat(message);
}
msg += EOL + EOL;
msg += "Resolution path: ".concat(resolutionPathString);
return _super.call(this, msg) || this;
}
return AwilixResolutionError;
}(AwilixError));
/**
* A nice error class so we can do an instanceOf check.
*/
var AwilixRegistrationError = /** @class */ (function (_super) {
__extends(AwilixRegistrationError, _super);
/**
* Constructor, takes the registered modules and unresolved tokens
* to create a message.
*
* @param {string|symbol} name
* The name of the module that could not be registered.
*/
function AwilixRegistrationError(name, message) {
var stringName = name.toString();
var msg = "Could not register '".concat(stringName, "'.");
if (message) {
msg += " ".concat(message);
}
return _super.call(this, msg) || this;
}
return AwilixRegistrationError;
}(AwilixError));
/**
* Resolution modes.
*/
const InjectionMode = {
/**
* The dependencies will be resolved by injecting the cradle proxy.
*
* @type {String}
*/
PROXY: 'PROXY',
/**
* The dependencies will be resolved by inspecting parameter names of the function/constructor.
*
* @type {String}
*/
CLASSIC: 'CLASSIC',
};
/**
* Resolution modes.
*/
var InjectionMode = {
/**
* The dependencies will be resolved by injecting the cradle proxy.
*
* @type {String}
*/
PROXY: 'PROXY',
/**
* The dependencies will be resolved by inspecting parameter names of the function/constructor.
*
* @type {String}
*/
CLASSIC: 'CLASSIC',
};
/**
* Lifetime types.
*/
const Lifetime = {
/**
* The registration will be resolved once and only once.
* @type {String}
*/
SINGLETON: 'SINGLETON',
/**
* The registration will be resolved every time (never cached).
* @type {String}
*/
TRANSIENT: 'TRANSIENT',
/**
* The registration will be resolved once per scope.
* @type {String}
*/
SCOPED: 'SCOPED',
};
/**
* Returns true if and only if the first lifetime is strictly longer than the second.
*/
function isLifetimeLonger(a, b) {
return ((a === Lifetime.SINGLETON && b !== Lifetime.SINGLETON) ||
(a === Lifetime.SCOPED && b === Lifetime.TRANSIENT));
}
/**
* Lifetime types.
*/
var Lifetime = {
/**
* The registration will be resolved once and only once.
* @type {String}
*/
SINGLETON: 'SINGLETON',
/**
* The registration will be resolved every time (never cached).
* @type {String}
*/
TRANSIENT: 'TRANSIENT',
/**
* The registration will be resolved once per scope.
* @type {String}
*/
SCOPED: 'SCOPED',
};
/**
* Returns true if and only if the first lifetime is strictly longer than the second.
*/
function isLifetimeLonger(a, b) {
return ((a === Lifetime.SINGLETON && b !== Lifetime.SINGLETON) ||
(a === Lifetime.SCOPED && b === Lifetime.TRANSIENT));
}
/**
* Creates a tokenizer for the specified source.
*
* @param source
*/
function createTokenizer(source) {
const end = source.length;
let pos = 0;
let type = 'EOF';
let value = '';
let flags = 0 /* TokenizerFlags.None */;
// These are used to greedily skip as much as possible.
// Whenever we reach a paren, we increment these.
let parenLeft = 0;
let parenRight = 0;
return {
next,
done,
};
/**
* Advances the tokenizer and returns the next token.
*/
function next(nextFlags = 0 /* TokenizerFlags.None */) {
flags = nextFlags;
advance();
return createToken();
}
/**
* Advances the tokenizer state.
*/
function advance() {
value = '';
type = 'EOF';
while (true) {
if (pos >= end) {
return (type = 'EOF');
}
const ch = source.charAt(pos);
// Whitespace is irrelevant
if (isWhiteSpace(ch)) {
pos++;
continue;
}
switch (ch) {
case '(':
pos++;
parenLeft++;
return (type = ch);
case ')':
pos++;
parenRight++;
return (type = ch);
case '*':
pos++;
return (type = ch);
case ',':
pos++;
return (type = ch);
case '=':
pos++;
if ((flags & 1 /* TokenizerFlags.Dumb */) === 0) {
// Not in dumb-mode, so attempt to skip.
skipExpression();
}
// We need to know that there's a default value so we can
// skip it if it does not exist when resolving.
return (type = ch);
case '/': {
pos++;
const nextCh = source.charAt(pos);
if (nextCh === '/') {
skipUntil((c) => c === '\n', true);
pos++;
}
if (nextCh === '*') {
skipUntil((c) => {
const closing = source.charAt(pos + 1);
return c === '*' && closing === '/';
}, true);
pos++;
}
continue;
}
default:
// Scans an identifier.
if (isIdentifierStart(ch)) {
scanIdentifier();
return type;
}
// Elegantly skip over tokens we don't care about.
pos++;
}
}
}
/**
* Scans an identifier, given it's already been proven
* we are ready to do so.
*/
function scanIdentifier() {
const identStart = source.charAt(pos);
const start = ++pos;
while (isIdentifierPart(source.charAt(pos))) {
pos++;
}
value = '' + identStart + source.substring(start, pos);
type = value === 'function' || value === 'class' ? value : 'ident';
if (type !== 'ident') {
value = '';
}
return value;
}
/**
* Skips everything until the next comma or the end of the parameter list.
* Checks the parenthesis balance so we correctly skip function calls.
*/
function skipExpression() {
skipUntil((ch) => {
const isAtRoot = parenLeft === parenRight + 1;
if (ch === ',' && isAtRoot) {
return true;
}
if (ch === '(') {
parenLeft++;
return false;
}
if (ch === ')') {
parenRight++;
if (isAtRoot) {
return true;
}
}
return false;
});
}
/**
* Skips strings and whilespace until the predicate is true.
*
* @param callback stops skipping when this returns `true`.
* @param dumb if `true`, does not skip whitespace and strings;
* it only stops once the callback returns `true`.
*/
function skipUntil(callback, dumb = false) {
while (pos < source.length) {
const ch = source.charAt(pos);
if (callback(ch)) {
return;
}
if (!dumb) {
if (isWhiteSpace(ch)) {
pos++;
continue;
}
if (isStringQuote(ch)) {
skipString();
continue;
}
}
pos++;
}
}
/**
* Given the current position is at a string quote, skips the entire string.
*/
function skipString() {
const quote = source.charAt(pos);
pos++;
while (pos < source.length) {
const ch = source.charAt(pos);
const prev = source.charAt(pos - 1);
// Checks if the quote was escaped.
if (ch === quote && prev !== '\\') {
pos++;
return;
}
// Template strings are a bit tougher, we want to skip the interpolated values.
if (quote === '`') {
const next = source.charAt(pos + 1);
if (next === '$') {
const afterDollar = source.charAt(pos + 2);
if (afterDollar === '{') {
// This is the start of an interpolation; skip the ${
pos = pos + 2;
// Skip strings and whitespace until we reach the ending }.
// This includes skipping nested interpolated strings. :D
skipUntil((ch) => ch === '}');
}
}
}
pos++;
}
}
/**
* Creates a token from the current state.
*/
function createToken() {
if (value) {
return { value, type };
}
return { type };
}
/**
* Determines if we are done parsing.
*/
function done() {
return type === 'EOF';
}
}
/**
* Determines if the given character is a whitespace character.
*
* @param {string} ch
* @return {boolean}
*/
function isWhiteSpace(ch) {
switch (ch) {
case '\r':
case '\n':
case ' ':
return true;
}
return false;
}
/**
* Determines if the specified character is a string quote.
* @param {string} ch
* @return {boolean}
*/
function isStringQuote(ch) {
switch (ch) {
case "'":
case '"':
case '`':
return true;
}
return false;
}
// NOTE: I've added the `.` character so that member expression paths
// are seen as identifiers. This is so we don't get a constructor token for
// stuff like `MyClass.prototype.constructor()`
const IDENT_START_EXPR = /^[_$a-zA-Z\xA0-\uFFFF]$/;
const IDENT_PART_EXPR = /^[._$a-zA-Z0-9\xA0-\uFFFF]$/;
/**
* Determines if the character is a valid JS identifier start character.
*/
function isIdentifierStart(ch) {
return IDENT_START_EXPR.test(ch);
}
/**
* Determines if the character is a valid JS identifier start character.
*/
function isIdentifierPart(ch) {
return IDENT_PART_EXPR.test(ch);
}
/**
* Creates a tokenizer for the specified source.
*
* @param source
*/
function createTokenizer(source) {
var end = source.length;
var pos = 0;
var type = 'EOF';
var value = '';
var flags = 0 /* TokenizerFlags.None */;
// These are used to greedily skip as much as possible.
// Whenever we reach a paren, we increment these.
var parenLeft = 0;
var parenRight = 0;
return {
next: next,
done: done,
};
/**
* Advances the tokenizer and returns the next token.
*/
function next(nextFlags) {
if (nextFlags === void 0) { nextFlags = 0 /* TokenizerFlags.None */; }
flags = nextFlags;
advance();
return createToken();
}
/**
* Advances the tokenizer state.
*/
function advance() {
value = '';
type = 'EOF';
while (true) {
if (pos >= end) {
return (type = 'EOF');
}
var ch = source.charAt(pos);
// Whitespace is irrelevant
if (isWhiteSpace(ch)) {
pos++;
continue;
}
switch (ch) {
case '(':
pos++;
parenLeft++;
return (type = ch);
case ')':
pos++;
parenRight++;
return (type = ch);
case '*':
pos++;
return (type = ch);
case ',':
pos++;
return (type = ch);
case '=':
pos++;
if ((flags & 1 /* TokenizerFlags.Dumb */) === 0) {
// Not in dumb-mode, so attempt to skip.
skipExpression();
}
// We need to know that there's a default value so we can
// skip it if it does not exist when resolving.
return (type = ch);
case '/': {
pos++;
var nextCh = source.charAt(pos);
if (nextCh === '/') {
skipUntil(function (c) { return c === '\n'; }, true);
pos++;
}
if (nextCh === '*') {
skipUntil(function (c) {
var closing = source.charAt(pos + 1);
return c === '*' && closing === '/';
}, true);
pos++;
}
continue;
}
default:
// Scans an identifier.
if (isIdentifierStart(ch)) {
scanIdentifier();
return type;
}
// Elegantly skip over tokens we don't care about.
pos++;
}
}
}
/**
* Scans an identifier, given it's already been proven
* we are ready to do so.
*/
function scanIdentifier() {
var identStart = source.charAt(pos);
var start = ++pos;
while (isIdentifierPart(source.charAt(pos))) {
pos++;
}
value = '' + identStart + source.substring(start, pos);
type = value === 'function' || value === 'class' ? value : 'ident';
if (type !== 'ident') {
value = '';
}
return value;
}
/**
* Skips everything until the next comma or the end of the parameter list.
* Checks the parenthesis balance so we correctly skip function calls.
*/
function skipExpression() {
skipUntil(function (ch) {
var isAtRoot = parenLeft === parenRight + 1;
if (ch === ',' && isAtRoot) {
return true;
}
if (ch === '(') {
parenLeft++;
return false;
}
if (ch === ')') {
parenRight++;
if (isAtRoot) {
return true;
}
}
return false;
});
}
/**
* Skips strings and whilespace until the predicate is true.
*
* @param callback stops skipping when this returns `true`.
* @param dumb if `true`, does not skip whitespace and strings;
* it only stops once the callback returns `true`.
*/
function skipUntil(callback, dumb) {
if (dumb === void 0) { dumb = false; }
while (pos < source.length) {
var ch = source.charAt(pos);
if (callback(ch)) {
return;
}
if (!dumb) {
if (isWhiteSpace(ch)) {
pos++;
continue;
}
if (isStringQuote(ch)) {
skipString();
continue;
}
}
pos++;
}
}
/**
* Given the current position is at a string quote, skips the entire string.
*/
function skipString() {
var quote = source.charAt(pos);
pos++;
while (pos < source.length) {
var ch = source.charAt(pos);
var prev = source.charAt(pos - 1);
// Checks if the quote was escaped.
if (ch === quote && prev !== '\\') {
pos++;
return;
}
// Template strings are a bit tougher, we want to skip the interpolated values.
if (quote === '`') {
var next_1 = source.charAt(pos + 1);
if (next_1 === '$') {
var afterDollar = source.charAt(pos + 2);
if (afterDollar === '{') {
// This is the start of an interpolation; skip the ${
pos = pos + 2;
// Skip strings and whitespace until we reach the ending }.
// This includes skipping nested interpolated strings. :D
skipUntil(function (ch) { return ch === '}'; });
}
}
}
pos++;
}
}
/**
* Creates a token from the current state.
*/
function createToken() {
if (value) {
return { value: value, type: type };
}
return { type: type };
}
/**
* Determines if we are done parsing.
*/
function done() {
return type === 'EOF';
}
}
/**
* Determines if the given character is a whitespace character.
*
* @param {string} ch
* @return {boolean}
*/
function isWhiteSpace(ch) {
switch (ch) {
case '\r':
case '\n':
case ' ':
return true;
}
return false;
}
/**
* Determines if the specified character is a string quote.
* @param {string} ch
* @return {boolean}
*/
function isStringQuote(ch) {
switch (ch) {
case "'":
case '"':
case '`':
return true;
}
return false;
}
// NOTE: I've added the `.` character so that member expression paths
// are seen as identifiers. This is so we don't get a constructor token for
// stuff like `MyClass.prototype.constructor()`
var IDENT_START_EXPR = /^[_$a-zA-Z\xA0-\uFFFF]$/;
var IDENT_PART_EXPR = /^[._$a-zA-Z0-9\xA0-\uFFFF]$/;
/**
* Determines if the character is a valid JS identifier start character.
*/
function isIdentifierStart(ch) {
return IDENT_START_EXPR.test(ch);
}
/**
* Determines if the character is a valid JS identifier start character.
*/
function isIdentifierPart(ch) {
return IDENT_PART_EXPR.test(ch);
}
/**
* Quick flatten utility to flatten a 2-dimensional array.
*
* @param {Array<Array<Item>>} array
* The array to flatten.
*
* @return {Array<Item>}
* The flattened array.
*/
function flatten(array) {
const result = [];
array.forEach((arr) => {
arr.forEach((item) => {
result.push(item);
});
});
return result;
}
/**
* Creates a { name: value } object if the input isn't already in that format.
*
* @param {string|object} name
* Either a string or an object.
*
* @param {*} value
* The value, only used if name is not an object.
*
* @return {object}
*/
function nameValueToObject(name, value) {
const obj = name;
if (typeof obj === 'string' || typeof obj === 'symbol') {
return { [name]: value };
}
return obj;
}
/**
* Returns the last item in the array.
*
* @param {*[]} arr
* The array.
*
* @return {*}
* The last element.
*/
function last(arr) {
return arr[arr.length - 1];
}
/**
* Determines if the given function is a class.
*
* @param {Function} fn
* @return {boolean}
*/
function isClass(
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
fn) {
if (typeof fn !== 'function') {
return false;
}
// Should only need 2 tokens.
const tokenizer = createTokenizer(fn.toString());
const first = tokenizer.next();
if (first.type === 'class') {
return true;
}
const second = tokenizer.next();
if (first.type === 'function' && second.value) {
if (second.value[0] === second.value[0].toUpperCase()) {
return true;
}
}
return false;
}
/**
* Determines if the given value is a function.
*
* @param {unknown} val
* Any value to check if it's a function.
*
* @return {boolean}
* true if the value is a function, false otherwise.
*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
function isFunction(val) {
return typeof val === 'function';
}
/**
* Returns the unique items in the array.
*
* @param {Array<T>}
* The array to remove dupes from.
*
* @return {Array<T>}
* The deduped array.
*/
function uniq(arr) {
return Array.from(new Set(arr));
}
/**
* Creates a { name: value } object if the input isn't already in that format.
*
* @param {string|object} name
* Either a string or an object.
*
* @param {*} value
* The value, only used if name is not an object.
*
* @return {object}
*/
function nameValueToObject(name, value) {
var _a;
var obj = name;
if (typeof obj === 'string' || typeof obj === 'symbol') {
return _a = {}, _a[name] = value, _a;
}
return obj;
}
/**
* Returns the last item in the array.
*
* @param {*[]} arr
* The array.
*
* @return {*}
* The last element.
*/
function last(arr) {
return arr[arr.length - 1];
}
/**
* Determines if the given function is a class.
*
* @param {Function} fn
* @return {boolean}
*/
function isClass(
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
fn) {
if (typeof fn !== 'function') {
return false;
}
// Should only need 2 tokens.
var tokenizer = createTokenizer(fn.toString());
var first = tokenizer.next();
if (first.type === 'class') {
return true;
}
var second = tokenizer.next();
if (first.type === 'function' && second.value) {
if (second.value[0] === second.value[0].toUpperCase()) {
return true;
}
}
return false;
}
/**
* Determines if the given value is a function.
*
* @param {unknown} val
* Any value to check if it's a function.
*
* @return {boolean}
* true if the value is a function, false otherwise.
*/
function isFunction(val) {
return typeof val === 'function';
}
/**
* Returns the unique items in the array.
*
* @param {Array<T>}
* The array to remove dupes from.
*
* @return {Array<T>}
* The deduped array.
*/
function uniq(arr) {
return Array.from(new Set(arr));
}
// Regex to extract the module name.
const nameExpr = /(.*)\..*/i;
/**
* Internal method for globbing a single pattern.
*
* @param {String} globPattern
* The glob pattern.
*
* @param {String} opts.cwd
* Current working directory, used for resolving filepaths.
* Defaults to `process.cwd()`.
*
* @return {[{name, path, opts}]}
* The module names and paths.
*
* @api private
*/
function _listModules(globPattern, opts) {
opts = { cwd: process.cwd(), glob: glob__namespace.sync, ...opts };
let patternOpts = null;
if (Array.isArray(globPattern)) {
patternOpts = globPattern[1];
globPattern = globPattern[0];
}
// Replace Windows path separators with Posix path
globPattern = globPattern.replace(/\\/g, '/');
const result = opts.glob(globPattern, { cwd: opts.cwd });
const mapped = result.map((p) => ({
name: nameExpr.exec(path__namespace.basename(p))[1],
path: path__namespace.resolve(opts.cwd, p),
opts: patternOpts,
}));
return mapped;
}
/**
* Returns a list of {name, path} pairs,
* where the name is the module name, and path is the actual
* full path to the module.
*
* @param {String|Array<String>} globPatterns
* The glob pattern as a string or an array of strings.
*
* @param {String} opts.cwd
* Current working directory, used for resolving filepaths.
* Defaults to `process.cwd()`.
*
* @return {[{name, path}]}
* An array of objects with the module names and paths.
*/
function listModules(globPatterns, opts) {
if (Array.isArray(globPatterns)) {
return flatten(globPatterns.map((p) => _listModules(p, opts)));
}
return _listModules(globPatterns, opts);
}
/*
* Parses the parameter list of a function string, including ES6 class constructors.
*
* @param {string} source
* The source of a function to extract the parameter list from
*
* @return {Array<Parameter> | null}
* Returns an array of parameters, or `null` if no
* constructor was found for a class.
*/
function parseParameterList(source) {
var _a = createTokenizer(source), _next = _a.next, done = _a.done;
var params = [];
var t = null;
nextToken();
while (!done()) {
switch (t.type) {
case 'class':
skipUntilConstructor();
// If we didn't find a constructor token, then we know that there
// are no dependencies in the defined class.
if (!isConstructorToken()) {
return null;
}
// Next token is the constructor identifier.
nextToken();
break;
case 'function': {
var next = nextToken();
if (next.type === 'ident' || next.type === '*') {
// This is the function name or a generator star. Skip it.
nextToken();
}
break;
}
case '(':
// Start parsing parameter names.
parseParams();
break;
case ')':
// We're now out of the parameter list.
return params;
case 'ident': {
// Likely a paren-less arrow function
// which can have no default args.
var param = { name: t.value, optional: false };
if (t.value === 'async') {
// Given it's the very first token, we can assume it's an async function,
// so skip the async keyword if the next token is not an equals sign, in which
// case it is a single-arg arrow func.
var next = nextToken();
if (next && next.type !== '=') {
break;
}
}
params.push(param);
return params;
}
/* istanbul ignore next */
default:
throw unexpected();
}
}
return params;
/**
* After having been placed within the parameter list of
* a function, parses the parameters.
*/
function parseParams() {
// Current token is a left-paren
var param = { name: '', optional: false };
while (!done()) {
nextToken();
switch (t.type) {
case 'ident':
param.name = t.value;
break;
case '=':
param.optional = true;
break;
case ',':
params.push(param);
param = { name: '', optional: false };
break;
case ')':
if (param.name) {
params.push(param);
}
return;
/* istanbul ignore next */
default:
throw unexpected();
}
}
}
/**
* Skips until we reach the constructor identifier.
*/
function skipUntilConstructor() {
while (!isConstructorToken() && !done()) {
nextToken(1 /* TokenizerFlags.Dumb */);
}
}
/**
* Determines if the current token represents a constructor, and the next token after it is a paren
* @return {boolean}
*/
function isConstructorToken() {
return t.type === 'ident' && t.value === 'constructor';
}
/**
* Advances the tokenizer and stores the previous token in history
*/
function nextToken(flags) {
if (flags === void 0) { flags = 0 /* TokenizerFlags.None */; }
t = _next(flags);
return t;
}
/**
* Returns an error describing an unexpected token.
*/
/* istanbul ignore next */
function unexpected() {
return new SyntaxError("Parsing parameter list, did not expect ".concat(t.type, " token").concat(t.value ? " (".concat(t.value, ")") : ''));
}
}
/*
* Parses the parameter list of a function string, including ES6 class constructors.
*
* @param {string} source
* The source of a function to extract the parameter list from
*
* @return {Array<Parameter> | null}
* Returns an array of parameters, or `null` if no
* constructor was found for a class.
*/
function parseParameterList(source) {
const { next: _next, done } = createTokenizer(source);
const params = [];
let t = null;
nextToken();
while (!done()) {
switch (t.type) {
case 'class':
skipUntilConstructor();
// If we didn't find a constructor token, then we know that there
// are no dependencies in the defined class.
if (!isConstructorToken()) {
return null;
}
// Next token is the constructor identifier.
nextToken();
break;
case 'function': {
const next = nextToken();
if (next.type === 'ident' || next.type === '*') {
// This is the function name or a generator star. Skip it.
nextToken();
}
break;
}
case '(':
// Start parsing parameter names.
parseParams();
break;
case ')':
// We're now out of the parameter list.
return params;
case 'ident': {
// Likely a paren-less arrow function
// which can have no default args.
const param = { name: t.value, optional: false };
if (t.value === 'async') {
// Given it's the very first token, we can assume it's an async function,
// so skip the async keyword if the next token is not an equals sign, in which
// case it is a single-arg arrow func.
const next = nextToken();
if (next && next.type !== '=') {
break;
}
}
params.push(param);
return params;
}
/* istanbul ignore next */
default:
throw unexpected();
}
}
return params;
/**
* After having been placed within the parameter list of
* a function, parses the parameters.
*/
function parseParams() {
// Current token is a left-paren
let param = { name: '', optional: false };
while (!done()) {
nextToken();
switch (t.type) {
case 'ident':
param.name = t.value;
break;
case '=':
param.optional = true;
break;
case ',':
params.push(param);
param = { name: '', optional: false };
break;
case ')':
if (param.name) {
params.push(param);
}
return;
/* istanbul ignore next */
default:
throw unexpected();
}
}
}
/**
* Skips until we reach the constructor identifier.
*/
function skipUntilConstructor() {
while (!isConstructorToken() && !done()) {
nextToken(1 /* TokenizerFlags.Dumb */);
}
}
/**
* Determines if the current token represents a constructor, and the next token after it is a paren
* @return {boolean}
*/
function isConstructorToken() {
return t.type === 'ident' && t.value === 'constructor';
}
/**
* Advances the tokenizer and stores the previous token in history
*/
function nextToken(flags = 0 /* TokenizerFlags.None */) {
t = _next(flags);
return t;
}
/**
* Returns an error describing an unexpected token.
*/
/* istanbul ignore next */
function unexpected() {
return new SyntaxError(`Parsing parameter list, did not expect ${t.type} token${t.value ? ` (${t.value})` : ''}`);
}
}
// We parse the signature of any `Function`, so we want to allow `Function` types.
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
/**
* RESOLVER symbol can be used by modules loaded by
* `loadModules` to configure their lifetime, injection mode, etc.
*/
var RESOLVER = Symbol('Awilix Resolver Config');
/**
* Creates a simple value resolver where the given value will always be resolved. The value is
* marked as leak-safe since in strict mode, the value will only be resolved when it is not leaking
* upwards from a child scope to a parent singleton.
*
* @param {string} name The name to register the value as.
*
* @param {*} value The value to resolve.
*
* @return {object} The resolver.
*/
function asValue(value) {
return {
resolve: function () { return value; },
isLeakSafe: true,
};
}
/**
* Creates a factory resolver, where the given factory function
* will be invoked with `new` when requested.
*
* @param {string} name
* The name to register the value as.
*
* @param {Function} fn
* The function to register.
*
* @param {object} opts
* Additional options for the resolver.
*
* @return {object}
* The resolver.
*/
function asFunction(fn, opts) {
if (!isFunction(fn)) {
throw new AwilixTypeError('asFunction', 'fn', 'function', fn);
}
var defaults = {
lifetime: Lifetime.TRANSIENT,
};
opts = makeOptions(defaults, opts, fn[RESOLVER]);
var resolve = generateResolve(fn);
var result = __assign({ resolve: resolve }, opts);
return createDisposableResolver(createBuildResolver(result));
}
/**
* Like a factory resolver, but for classes that require `new`.
*
* @param {string} name
* The name to register the value as.
*
* @param {Class} Type
* The function to register.
*
* @param {object} opts
* Additional options for the resolver.
*
* @return {object}
* The resolver.
*/
function asClass(Type, opts) {
if (!isFunction(Type)) {
throw new AwilixTypeError('asClass', 'Type', 'class', Type);
}
var defaults = {
lifetime: Lifetime.TRANSIENT,
};
opts = makeOptions(defaults, opts, Type[RESOLVER]);
// A function to handle object construction for us, as to make the generateResolve more reusable
var newClass = function newClass() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return Reflect.construct(Type, args);
};
var resolve = generateResolve(newClass, Type);
return createDisposableResolver(createBuildResolver(__assign(__assign({}, opts), { resolve: resolve })));
}
/**
* Resolves to the specified registration. Marked as leak-safe since the alias target is what should
* be checked for lifetime leaks.
*/
function aliasTo(name) {
return {
resolve: function (container) {
return container.resolve(name);
},
isLeakSafe: true,
};
}
/**
* Given an options object, creates a fluid interface
* to manage it.
*
* @param {*} obj
* The object to return.
*
* @return {object}
* The interface.
*/
function createBuildResolver(obj) {
function setLifetime(value) {
return createBuildResolver(__assign(__assign({}, this), { lifetime: value }));
}
function setInjectionMode(value) {
return createBuildResolver(__assign(__assign({}, this), { injectionMode: value }));
}
function inject(injector) {
return createBuildResolver(__assign(__assign({}, this), { injector: injector }));
}
return updateResolver(obj, {
setLifetime: setLifetime,
inject: inject,
transient: partial(setLifetime, Lifetime.TRANSIENT),
scoped: partial(setLifetime, Lifetime.SCOPED),
singleton: partial(setLifetime, Lifetime.SINGLETON),
setInjectionMode: setInjectionMode,
proxy: partial(setInjectionMode, InjectionMode.PROXY),
classic: partial(setInjectionMode, InjectionMode.CLASSIC),
});
}
/**
* Given a resolver, returns an object with methods to manage the disposer
* function.
* @param obj
*/
function createDisposableResolver(obj) {
function disposer(dispose) {
return createDisposableResolver(__assign(__assign({}, this), { dispose: dispose }));
}
return updateResolver(obj, {
disposer: disposer,
});
}
/**
* Partially apply arguments to the given function.
*/
function partial(fn, arg1) {
return function partiallyApplied() {
return fn.call(this, arg1);
};
}
/**
* Makes an options object based on defaults.
*
* @param {object} defaults
* Default options.
*
* @param {...} rest
* The input to check and possibly assign to the resulting object
*
* @return {object}
*/
function makeOptions(defaults) {
var rest = [];
for (var _i = 1; _i < arguments.length; _i++) {
rest[_i - 1] = arguments[_i];
}
return Object.assign.apply(Object, __spreadArray([{}, defaults], rest, false));
}
/**
* Creates a new resolver with props merged from both.
*
* @param source
* @param target
*/
function updateResolver(source, target) {
var result = __assign(__assign({}, source), target);
return result;
}
/**
* Returns a wrapped `resolve` function that provides values
* from the injector and defers to `container.resolve`.
*
* @param {AwilixContainer} container
* @param {Object} locals
* @return {Function}
*/
function wrapWithLocals(container, locals) {
return function wrappedResolve(name, resolveOpts) {
if (name in locals) {
return locals[name];
}
return container.resolve(name, resolveOpts);
};
}
/**
* Returns a new Proxy that checks the result from `injector`
* for values before delegating to the actual container.
*
* @param {Object} cradle
* @param {Function} injector
* @return {Proxy}
*/
function createInjectorProxy(container, injector) {
var locals = injector(container);
var allKeys = uniq(__spreadArray(__spreadArray([], Reflect.ownKeys(container.cradle), true), Reflect.ownKeys(locals), true));
// TODO: Lots of duplication here from the container proxy.
// Need to refactor.
var proxy = new Proxy({}, {
/**
* Resolves the value by first checking the locals, then the container.
*/
get: function (target, name) {
if (name === Symbol.iterator) {
return function iterateRegistrationsAndLocals() {
var _a, _b, _c, _i, prop, _d, _e, _f, _g, prop;
return __generator(this, function (_h) {
switch (_h.label) {
case 0:
_a = container.cradle;
_b = [];
for (_c in _a)
_b.push(_c);
_i = 0;
_h.label = 1;
case 1:
if (!(_i < _b.length)) return [3 /*break*/, 4];
_c = _b[_i];
if (!(_c in _a)) return [3 /*break*/, 3];
prop = _c;
return [4 /*yield*/, prop];
case 2:
_h.sent();
_h.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4:
_d = locals;
_e = [];
for (_f in _d)
_e.push(_f);
_g = 0;
_h.label = 5;
case 5:
if (!(_g < _e.length)) return [3 /*break*/, 8];
_f = _e[_g];
if (!(_f in _d)) return [3 /*break*/, 7];
prop = _f;
return [4 /*yield*/, prop];
case 6:
_h.sent();
_h.label = 7;
case 7:
_g++;
return [3 /*break*/, 5];
case 8: return [2 /*return*/];
}
});
};
}
if (name in locals) {
return locals[name];
}
return container.resolve(name);
},
/**
* Used for `Object.keys`.
*/
ownKeys: function () {
return allKeys;
},
/**
* Used for `Object.keys`.
*/
getOwnPropertyDescriptor: function (target, key) {
if (allKeys.indexOf(key) > -1) {
return {
enumerable: true,
configurable: true,
};
}
return undefined;
},
});
return proxy;
}
/**
* Returns a resolve function used to construct the dependency graph
*
* @this {Registration}
* The `this` context is a resolver.
*
* @param {Function} fn
* The function to construct
*
* @param {Function} dependencyParseTarget
* The function to parse for the dependencies of the construction target
*
* @param {boolean} isFunction
* Is the resolution target an actual function or a mask for a constructor?
*
* @return {Function}
* The function used for dependency resolution
*/
function generateResolve(fn, dependencyParseTarget) {
// If the function used for dependency parsing is falsy, use the supplied function
if (!dependencyParseTarget) {
dependencyParseTarget = fn;
}
// Parse out the dependencies
// NOTE: we do this regardless of whether PROXY is used or not,
// because if this fails, we want it to fail early (at startup) rather
// than at resolution time.
var dependencies = parseDependencies(dependencyParseTarget);
// Use a regular function instead of an arrow function to facilitate binding to the resolver.
return function resolve(container) {
// Because the container holds a global reolutionMode we need to determine it in the proper order of precedence:
// resolver -> container -> default value
var injectionMode = this.injectionMode ||
container.options.injectionMode ||
InjectionMode.PROXY;
if (injectionMode !== InjectionMode.CLASSIC) {
// If we have a custom injector, we need to wrap the cradle.
var cradle = this.injector
? createInjectorProxy(container, this.injector)
: container.cradle;
// Return the target injected with the cradle
return fn(cradle);
}
// We have dependencies so we need to resolve them manually
if (dependencies.length > 0) {
var resolve_1 = this.injector
? wrapWithLocals(container, this.injector(container))
: container.resolve;
var children = dependencies.map(function (p) {
return resolve_1(p.name, { allowUnregistered: p.optional });
});
return fn.apply(void 0, children);
}
return fn();
};
}
/**
* Parses the dependencies from the given function.
* If it's a class that extends another class, and it does
* not have a defined constructor, attempt to parse it's super constructor.
*/
function parseDependencies(fn) {
var result = parseParameterList(fn.toString());
if (!result) {
// No defined constructor for a class, check if there is a parent
// we can parse.
var parent = Object.getPrototypeOf(fn);
if (typeof parent === 'function' && parent !== Function.prototype) {
// Try to parse the parent
return parseDependencies(parent);
}
return [];
}
return result;
}
// We parse the signature of any `Function`, so we want to allow `Function` types.
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
/**
* RESOLVER symbol can be used by modules loaded by
* `loadModules` to configure their lifetime, injection mode, etc.
*/
const RESOLVER = Symbol('Awilix Resolver Config');
/**
* Creates a simple value resolver where the given value will always be resolved. The value is
* marked as leak-safe since in strict mode, the value will only be resolved when it is not leaking
* upwards from a child scope to a parent singleton.
*
* @param {string} name The name to register the value as.
*
* @param {*} value The value to resolve.
*
* @return {object} The resolver.
*/
function asValue(value) {
return {
resolve: () => value,
isLeakSafe: true,
};
}
/**
* Creates a factory resolver, where the given factory function
* will be invoked with `new` when requested.
*
* @param {string} name
* The name to register the value as.
*
* @param {Function} fn
* The function to register.
*
* @param {object} opts
* Additional options for the resolver.
*
* @return {object}
* The resolver.
*/
function asFunction(fn, opts) {
if (!isFunction(fn)) {
throw new AwilixTypeError('asFunction', 'fn', 'function', fn);
}
const defaults = {
lifetime: Lifetime.TRANSIENT,
};
opts = makeOptions(defaults, opts, fn[RESOLVER]);
const resolve = generateResolve(fn);
const result = {
resolve,
...opts,
};
return createDisposableResolver(createBuildResolver(result));
}
/**
* Like a factory resolver, but for classes that require `new`.
*
* @param {string} name
* The name to register the value as.
*
* @param {Class} Type
* The function to register.
*
* @param {object} opts
* Additional options for the resolver.
*
* @return {object}
* The resolver.
*/
function asClass(Type, opts) {
if (!isFunction(Type)) {
throw new AwilixTypeError('asClass', 'Type', 'class', Type);
}
const defaults = {
lifetime: Lifetime.TRANSIENT,
};
opts = makeOptions(defaults, opts, Type[RESOLVER]);
// A function to handle object construction for us, as to make the generateResolve more reusable
const newClass = function newClass(...args) {
return Reflect.construct(Type, args);
};
const resolve = generateResolve(newClass, Type);
return createDisposableResolver(createBuildResolver({
...opts,
resolve,
}));
}
/**
* Resolves to the specified registration. Marked as leak-safe since the alias target is what should
* be checked for lifetime leaks.
*/
function aliasTo(name) {
return {
resolve(container) {
return container.resolve(name);
},
isLeakSafe: true,
};
}
/**
* Given an options object, creates a fluid interface
* to manage it.
*
* @param {*} obj
* The object to return.
*
* @return {object}
* The interface.
*/
function createBuildResolver(obj) {
function setLifetime(value) {
return createBuildResolver({
...this,
lifetime: value,
});
}
function setInjectionMode(value) {
return createBuildResolver({
...this,
injectionMode: value,
});
}
function inject(injector) {
return createBuildResolver({
...this,
injector,
});
}
return updateResolver(obj, {
setLifetime,
inject,
transient: partial(setLifetime, Lifetime.TRANSIENT),
scoped: partial(setLifetime, Lifetime.SCOPED),
singleton: partial(setLifetime, Lifetime.SINGLETON),
setInjectionMode,
proxy: partial(setInjectionMode, InjectionMode.PROXY),
classic: partial(setInjectionMode, InjectionMode.CLASSIC),
});
}
/**
* Given a resolver, returns an object with methods to manage the disposer
* function.
* @param obj
*/
function createDisposableResolver(obj) {
function disposer(dispose) {
return createDisposableResolver({
...this,
dispose,
});
}
return updateResolver(obj, {
disposer,
});
}
/**
* Partially apply arguments to the given function.
*/
function partial(fn, arg1) {
return function partiallyApplied() {
return fn.call(this, arg1);
};
}
/**
* Makes an options object based on defaults.
*
* @param {object} defaults
* Default options.
*
* @param {...} rest
* The input to check and possibly assign to the resulting object
*
* @return {object}
*/
function makeOptions(defaults, ...rest) {
return Object.assign({}, defaults, ...rest);
}
/**
* Creates a new resolver with props merged from both.
*
* @param source
* @param target
*/
function updateResolver(source, target) {
const result = {
...source,
...target,
};
return result;
}
/**
* Returns a wrapped `resolve` function that provides values
* from the injector and defers to `container.resolve`.
*
* @param {AwilixContainer} container
* @param {Object} locals
* @return {Function}
*/
function wrapWithLocals(container, locals) {
return function wrappedResolve(name, resolveOpts) {
if (name in locals) {
return locals[name];
}
return container.resolve(name, resolveOpts);
};
}
/**
* Returns a new Proxy that checks the result from `injector`
* for values before delegating to the actual container.
*
* @param {Object} cradle
* @param {Function} injector
* @return {Proxy}
*/
function createInjectorProxy(container, injector) {
const locals = injector(container);
const allKeys = uniq([
...Reflect.ownKeys(container.cradle),
...Reflect.ownKeys(locals),
]);
// TODO: Lots of duplication here from the container proxy.
// Need to refactor.
const proxy = new Proxy({}, {
/**
* Resolves the value by first checking the locals, then the container.
*/
get(target, name) {
if (name === Symbol.iterator) {
return function* iterateRegistrationsAndLocals() {
for (const prop in container.cradle) {
yield prop;
}
for (const prop in locals) {
yield prop;
}
};
}
if (name in locals) {
return locals[name];
}
return container.resolve(name);
},
/**
* Used for `Object.keys`.
*/
ownKeys() {
return allKeys;
},
/**
* Used for `Object.keys`.
*/
getOwnPropertyDescriptor(target, key) {
if (allKeys.indexOf(key) > -1) {
return {
enumerable: true,
configurable: true,
};
}
return undefined;
},
});
return proxy;
}
/**
* Returns a resolve function used to construct the dependency graph
*
* @this {Registration}
* The `this` context is a resolver.
*
* @param {Function} fn
* The function to construct
*
* @param {Function} dependencyParseTarget
* The function to parse for the dependencies of the construction target
*
* @param {boolean} isFunction
* Is the resolution target an actual function or a mask for a constructor?
*
* @return {Function}
* The function used for dependency resolution
*/
function generateResolve(fn, dependencyParseTarget) {
// If the function used for dependency parsing is falsy, use the supplied function
if (!dependencyParseTarget) {
dependencyParseTarget = fn;
}
// Parse out the dependencies
// NOTE: we do this regardless of whether PROXY is used or not,
// because if this fails, we want it to fail early (at startup) rather
// than at resolution time.
const dependencies = parseDependencies(dependencyParseTarget);
// Use a regular function instead of an arrow function to facilitate binding to the resolver.
return function resolve(container) {
// Because the container holds a global reolutionMode we need to determine it in the proper order of precedence:
// resolver -> container -> default value
const injectionMode = this.injectionMode ||
container.options.injectionMode ||
InjectionMode.PROXY;
if (injectionMode !== InjectionMode.CLASSIC) {
// If we have a custom injector, we need to wrap the cradle.
const cradle = this.injector
? createInjectorProxy(container, this.injector)
: container.cradle;
// Return the target injected with the cradle
return fn(cradle);
}
// We have dependencies so we need to resolve them manually
if (dependencies.length > 0) {
const resolve = this.injector
? wrapWithLocals(container, this.injector(container))
: container.resolve;
const children = dependencies.map((p) => resolve(p.name, { allowUnregistered: p.optional }));
return fn(...children);
}
return fn();
};
}
/**
* Parses the dependencies from the given function.
* If it's a class that extends another class, and it does
* not have a defined constructor, attempt to parse it's super constructor.
*/
function parseDependencies(fn) {
const result = parseParameterList(fn.toString());
if (!result) {
// No defined constructor for a class, check if there is a parent
// we can parse.
const parent = Object.getPrototypeOf(fn);
if (typeof parent === 'function' && parent !== Function.prototype) {
// Try to parse the parent
return parseDependencies(parent);
}
return [];
}
return result;
}
/**
* Family tree symbol.
*/
var FAMILY_TREE = Symbol('familyTree');
/**
* Roll Up Registrations symbol.
*/
var ROLL_UP_REGISTRATIONS = Symbol('rollUpRegistrations');
/**
* The string representation when calling toString.
*/
var CRADLE_STRING_TAG = 'AwilixContainerCradle';
/**
* Creates an Awilix container instance.
*
* @param {Function} options.require The require function to use. Defaults to require.
*
* @param {string} options.injectionMode The mode used by the container to resolve dependencies.
* Defaults to 'Proxy'.
*
* @param {boolean} options.strict True if the container should run in strict mode with additional
* validation for resolver configuration correctness. Defaults to false.
*
* @return {AwilixContainer<T>} The container.
*/
function createContainer(options) {
if (options === void 0) { options = {}; }
return createContainerInternal(options);
}
function createContainerInternal(options, parentContainer, parentResolutionStack) {
var _a;
options = __assign({ injectionMode: InjectionMode.PROXY, strict: false }, options);
/**
* Tracks the names and lifetimes of the modules being resolved. Used to detect circular
* dependencies and, in strict mode, lifetime leakage issues.
*/
var resolutionStack = parentResolutionStack !== null && parentResolutionStack !== void 0 ? parentResolutionStack : [];
// Internal registration store for this container.
var registrations = {};
/**
* The `Proxy` that is passed to functions so they can resolve their dependencies without
* knowing where they come from. I call it the "cradle" because
* it is where registered things come to life at resolution-time.
*/
var cradle = new Proxy({
/* removed in browser build */
}, {
/**
* The `get` handler is invoked whenever a get-call for `container.cradle.*` is made.
*
* @param {object} _target
* The proxy target. Irrelevant.
*
* @param {string} name
* The property name.
*
* @return {*}
* Whatever the resolve call returns.
*/
get: function (_target, name) { return resolve(name); },
/**
* Setting things on the cradle throws an error.
*
* @param {object} target
* @param {string} name
*/
set: function (_target, name) {
throw new Error("Attempted setting property \"".concat(name, "\" on container cradle - this is not allowed."));
},
/**
* Used for `Object.keys`.
*/
ownKeys: function () {
return Array.from(cradle);
},
/**
* Used for `Object.keys`.
*/
getOwnPropertyDescriptor: function (target, key) {
var regs = rollUpRegistrations();
if (Object.getOwnPropertyDescriptor(regs, key)) {
return {
enumerable: true,
configurable: true,
};
}
return undefined;
},
});
// The container being exposed.
var container = (_a = {
options: options,
cradle: cradle,
inspect: inspect,
cache: new Map(),
loadModules: function () { throw new Error("loadModules is not supported in the browser."); },
createScope: createScope,
register: register,
build: build,
resolve: resolve,
hasRegistration: hasRegistration,
dispose: dispose,
getRegistration: getRegistration
},
/* removed in browser build */
_a[ROLL_UP_REGISTRATIONS] = rollUpRegistrations,
Object.defineProperty(_a, "registrations", {
get: function () {
return rollUpRegistrations();
},
enumerable: false,
configurable: true
}),
_a);
// Track the family tree.
var familyTree = parentContainer
? [container].concat(parentContainer[FAMILY_TREE])
: [container];
container[FAMILY_TREE] = familyTree;
// We need a reference to the root container,
// so we can retrieve and store singletons.
var rootContainer = last(familyTree);
return container;
/**
* Used by util.inspect (which is used by console.log).
*/
function inspect() {
return "[AwilixContainer (".concat(parentContainer ? 'scoped, ' : '', "registrations: ").concat(Object.keys(container.registrations).length, ")]");
}
/**
* Rolls up registrations from the family tree.
*
* This can get pretty expensive. Only used when
* iterating the cradle proxy, which is not something
* that should be done in day-to-day use, mostly for debugging.
*
* @param {boolean} bustCache
* Forces a recomputation.
*
* @return {object}
* The merged registrations object.
*/
function rollUpRegistrations() {
return __assign(__assign({}, (parentContainer && parentContainer[ROLL_UP_REGISTRATIONS]())), registrations);
}
/**
* Used for providing an iterator to the cradle.
*/
function cradleIterator() {
var registrations, _a, _b, _c, _i, registrationName;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
registrations = rollUpRegistrations();
_a = registrations;
_b = [];
for (_c in _a)
_b.push(_c);
_i = 0;
_d.label = 1;
case 1:
if (!(_i < _b.length)) return [3 /*break*/, 4];
_c = _b[_i];
if (!(_c in _a)) return [3 /*break*/, 3];
registrationName = _c;
return [4 /*yield*/, registrationName];
case 2:
_d.sent();
_d.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
}
/**
* Creates a scoped container.
*
* @return {object}
* The scoped container.
*/
function createScope() {
return createContainerInternal(options, container, resolutionStack);
}
/**
* Adds a registration for a resolver.
*/
function register(arg1, arg2) {
var obj = nameValueToObject(arg1, arg2);
var keys = __spreadArray(__spreadArray([], Object.keys(obj), true), Object.getOwnPropertySymbols(obj), true);
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
var resolver = obj[key];
// If strict mode is enabled, check to ensure we are not registering a singleton on a non-root
// container.
if (options.strict && resolver.lifetime === Lifetime.SINGLETON) {
if (parentContainer) {
throw new AwilixRegistrationError(key, 'Cannot register a singleton on a scoped container.');
}
}
registrations[key] = resolver;
}
return container;
}
/**
* Returned to `util.inspect` and Symbol.toStringTag when attempting to resolve
* a custom inspector function on the cradle.
*/
function toStringRepresentationFn() {
return Object.prototype.toString.call(cradle);
}
/**
* Recursively gets a registration by name if it exists in the
* current container or any of its' parents.
*
* @param name {string | symbol} The registration name.
*/
function getRegistration(name) {
var resolver = registrations[name];
if (resolver) {
return resolver;
}
if (parentContainer) {
return parentContainer.getRegistration(name);
}
return null;
}
/**
* Resolves the registration with the given name.
*
* @param {string | symbol} name
* The name of the registration to resolve.
*
* @param {ResolveOptions} resolveOpts
* The resolve options.
*
* @return {any}
* Whatever was resolved.
*/
function resolve(name, resolveOpts) {
resolveOpts = resolveOpts || {};
try {
// Grab the registration by name.
var resolver = getRegistration(name);
if (resolutionStack.some(function (_a) {
var parentName = _a.name;
return parentName === name;
})) {
throw new AwilixResolutionError(name, resolutionStack, 'Cyclic dependencies detected.');
}
// Used in JSON.stringify.
if (name === 'toJSON') {
return toStringRepresentationFn;
}
// Used in console.log.
if (name === 'constructor') {
return createContainer;
}
if (!resolver) {
// Checks for some edge cases.
switch (name) {
// The following checks ensure that console.log on the cradle does not
// throw an error (issue #7).
case 'inspect':
case 'toString':
return toStringRepresentationFn;
case Symbol.toStringTag:
return CRADLE_STRING_TAG;
// Edge case: Promise unwrapping will look for a "then" property and attempt to call it.
// Return undefined so that we won't cause a resolution error. (issue #109)
case 'then':
return undefined;
// When using `Array.from` or spreading the cradle, this will
// return the registration names.
case Symbol.iterator:
return cradleIterator;
}
if (resolveOpts.allowUnregistered) {
return undefined;
}
throw new AwilixResolutionError(name, resolutionStack);
}
var lifetime_1 = resolver.lifetime || Lifetime.TRANSIENT;
// if we are running in strict mode, this resolver is not explicitly marked leak-safe, and any
// of the parents have a shorter lifetime than the one requested, throw an error.
if (options.strict && !resolver.isLeakSafe) {
var maybeLongerLifetimeParentIndex = resolutionStack.findIndex(function (_a) {
var parentLifetime = _a.lifetime;
return isLifetimeLonger(parentLifetime, lifetime_1);
});
if (maybeLongerLifetimeParentIndex > -1) {
throw new AwilixResolutionError(name, resolutionStack, "Dependency '".concat(name.toString(), "' has a shorter lifetime than its ancestor: '").concat(resolutionStack[maybeLongerLifetimeParentIndex].name.toString(), "'"));
}
}
// Pushes the currently-resolving module information onto the stack
resolutionStack.push({ name: name, lifetime: lifetime_1 });
// Do the thing
var cached = void 0;
var resolved = void 0;
switch (lifetime_1) {
case Lifetime.TRANSIENT:
// Transient lifetime means resolve every time.
resolved = resolver.resolve(container);
break;
case Lifetime.SINGLETON:
// Singleton lifetime means cache at all times, regardless of scope.
cached = rootContainer.cache.get(name);
if (!cached) {
// if we are running in strict mode, perform singleton resolution using the root
// container only.
resolved = resolver.resolve(options.strict ? rootContainer : container);
rootContainer.cache.set(name, { resolver: resolver, value: resolved });
}
else {
resolved = cached.value;
}
break;
case Lifetime.SCOPED:
// Scoped lifetime means that the container
// that resolves the registration also caches it.
// If this container cache does not have it,
// resolve and cache it rather than using the parent
// container's cache.
cached = container.cache.get(name);
if (cached !== undefined) {
// We found one!
resolved = cached.value;
break;
}
// If we still have not found one, we need to resolve and cache it.
resolved = resolver.resolve(container);
container.cache.set(name, { resolver: resolver, value: resolved });
break;
default:
throw new AwilixResolutionError(name, resolutionStack, "Unknown lifetime \"".concat(resolver.lifetime, "\""));
}
// Pop it from the stack again, ready for the next resolution
resolutionStack.pop();
return resolved;
}
catch (err) {
// When we get an error we need to reset the stack. Mutate the existing array rather than
// updating the reference to ensure all parent containers' stacks are also updated.
resolutionStack.length = 0;
throw err;
}
}
/**
* Checks if the registration with the given name exists.
*
* @param {string | symbol} name
* The name of the registration to resolve.
*
* @return {boolean}
* Whether or not the registration exists.
*/
function hasRegistration(name) {
return !!getRegistration(name);
}
/**
* Given a registration, class or function, builds it up and returns it.
* Does not cache it, this means that any lifetime configured in case of passing
* a registration will not be used.
*
* @param {Resolver|Constructor|Function} targetOrResolver
* @param {ResolverOptions} opts
*/
function build(targetOrResolver, opts) {
if (targetOrResolver && targetOrResolver.resolve) {
return targetOrResolver.resolve(container);
}
var funcName = 'build';
var paramName = 'targetOrResolver';
AwilixTypeError.assert(targetOrResolver, funcName, paramName, 'a registration, function or class', targetOrResolver);
AwilixTypeError.assert(typeof targetOrResolver === 'function', funcName, paramName, 'a function or class', targetOrResolver);
var resolver = isClass(targetOrResolver)
? asClass(targetOrResolver, opts)
: asFunction(targetOrResolver, opts);
return resolver.resolve(container);
}
/**
* Disposes this container and it's children, calling the disposer
* on all disposable registrations and clearing the cache.
*/
function dispose() {
var entries = Array.from(container.cache.entries());
container.cache.clear();
return Promise.all(entries.map(function (_a) {
var entry = _a[1];
var resolver = entry.resolver, value = entry.value;
var disposable = resolver;
if (disposable.dispose) {
return Promise.resolve().then(function () { return disposable.dispose(value); });
}
return Promise.resolve();
})).then(function () { return undefined; });
}
}
/**
* Family tree symbol.
*/
const FAMILY_TREE = Symbol('familyTree');
/**
* Roll Up Registrations symbol.
*/
const ROLL_UP_REGISTRATIONS = Symbol('rollUpRegistrations');
/**
* The string representation when calling toString.
*/
const CRADLE_STRING_TAG = 'AwilixContainerCradle';
/**
* Creates an Awilix container instance.
*
* @param {Function} options.require The require function to use. Defaults to require.
*
* @param {string} options.injectionMode The mode used by the container to resolve dependencies.
* Defaults to 'Proxy'.
*
* @param {boolean} options.strict True if the container should run in strict mode with additional
* validation for resolver configuration correctness. Defaults to false.
*
* @return {AwilixContainer<T>} The container.
*/
function createContainer(options = {}) {
return createContainerInternal(options);
}
function createContainerInternal(options, parentContainer, parentResolutionStack) {
options = {
injectionMode: InjectionMode.PROXY,
strict: false,
...options,
};
/**
* Tracks the names and lifetimes of the modules being resolved. Used to detect circular
* dependencies and, in strict mode, lifetime leakage issues.
*/
const resolutionStack = parentResolutionStack ?? [];
// Internal registration store for this container.
const registrations = {};
/**
* The `Proxy` that is passed to functions so they can resolve their dependencies without
* knowing where they come from. I call it the "cradle" because
* it is where registered things come to life at resolution-time.
*/
const cradle = new Proxy({
/* removed in browser build */
}, {
/**
* The `get` handler is invoked whenever a get-call for `container.cradle.*` is made.
*
* @param {object} _target
* The proxy target. Irrelevant.
*
* @param {string} name
* The property name.
*
* @return {*}
* Whatever the resolve call returns.
*/
get: (_target, name) => resolve(name),
/**
* Setting things on the cradle throws an error.
*
* @param {object} target
* @param {string} name
*/
set: (_target, name) => {
throw new Error(`Attempted setting property "${name}" on container cradle - this is not allowed.`);
},
/**
* Used for `Object.keys`.
*/
ownKeys() {
return Array.from(cradle);
},
/**
* Used for `Object.keys`.
*/
getOwnPropertyDescriptor(target, key) {
const regs = rollUpRegistrations();
if (Object.getOwnPropertyDescriptor(regs, key)) {
return {
enumerable: true,
configurable: true,
};
}
return undefined;
},
});
// The container being exposed.
const container = {
options,
cradle,
inspect,
cache: new Map(),
loadModules: () => { throw new Error("loadModules is not supported in the browser."); },
createScope,
register: register,
build,
resolve,
hasRegistration,
dispose,
getRegistration,
/* removed in browser build */
[ROLL_UP_REGISTRATIONS]: rollUpRegistrations,
get registrations() {
return rollUpRegistrations();
},
};
// Track the family tree.
const familyTree = parentContainer
? [container].concat(parentContainer[FAMILY_TREE])
: [container];
container[FAMILY_TREE] = familyTree;
// We need a reference to the root container,
// so we can retrieve and store singletons.
const rootContainer = last(familyTree);
return container;
/**
* Used by util.inspect (which is used by console.log).
*/
function inspect() {
return `[AwilixContainer (${parentContainer ? 'scoped, ' : ''}registrations: ${Object.keys(container.registrations).length})]`;
}
/**
* Rolls up registrations from the family tree.
*
* This can get pretty expensive. Only used when
* iterating the cradle proxy, which is not something
* that should be done in day-to-day use, mostly for debugging.
*
* @param {boolean} bustCache
* Forces a recomputation.
*
* @return {object}
* The merged registrations object.
*/
function rollUpRegistrations() {
return {
...(parentContainer && parentContainer[ROLL_UP_REGISTRATIONS]()),
...registrations,
};
}
/**
* Used for providing an iterator to the cradle.
*/
function* cradleIterator() {
const registrations = rollUpRegistrations();
for (const registrationName in registrations) {
yield registrationName;
}
}
/**
* Creates a scoped container.
*
* @return {object}
* The scoped container.
*/
function createScope() {
return createContainerInternal(options, container, resolutionStack);
}
/**
* Adds a registration for a resolver.
*/
function register(arg1, arg2) {
const obj = nameValueToObject(arg1, arg2);
const keys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
for (const key of keys) {
const resolver = obj[key];
// If strict mode is enabled, check to ensure we are not registering a singleton on a non-root
// container.
if (options.strict && resolver.lifetime === Lifetime.SINGLETON) {
if (parentContainer) {
throw new AwilixRegistrationError(key, 'Cannot register a singleton on a scoped container.');
}
}
registrations[key] = resolver;
}
return container;
}
/**
* Returned to `util.inspect` and Symbol.toStringTag when attempting to resolve
* a custom inspector function on the cradle.
*/
function toStringRepresentationFn() {
return Object.prototype.toString.call(cradle);
}
/**
* Recursively gets a registration by name if it exists in the
* current container or any of its' parents.
*
* @param name {string | symbol} The registration name.
*/
function getRegistration(name) {
const resolver = registrations[name];
if (resolver) {
return resolver;
}
if (parentContainer) {
return parentContainer.getRegistration(name);
}
return null;
}
/**
* Resolves the registration with the given name.
*
* @param {string | symbol} name
* The name of the registration to resolve.
*
* @param {ResolveOptions} resolveOpts
* The resolve options.
*
* @return {any}
* Whatever was resolved.
*/
function resolve(name, resolveOpts) {
resolveOpts = resolveOpts || {};
try {
// Grab the registration by name.
const resolver = getRegistration(name);
if (resolutionStack.some(({ name: parentName }) => parentName === name)) {
throw new AwilixResolutionError(name, resolutionStack, 'Cyclic dependencies detected.');
}
// Used in JSON.stringify.
if (name === 'toJSON') {
return toStringRepresentationFn;
}
// Used in console.log.
if (name === 'constructor') {
return createContainer;
}
if (!resolver) {
// Checks for some edge cases.
switch (name) {
// The following checks ensure that console.log on the cradle does not
// throw an error (issue #7).
case 'inspect':
case 'toString':
return toStringRepresentationFn;
case Symbol.toStringTag:
return CRADLE_STRING_TAG;
// Edge case: Promise unwrapping will look for a "then" property and attempt to call it.
// Return undefined so that we won't cause a resolution error. (issue #109)
case 'then':
return undefined;
// When using `Array.from` or spreading the cradle, this will
// return the registration names.
case Symbol.iterator:
return cradleIterator;
}
if (resolveOpts.allowUnregistered) {
return undefined;
}
throw new AwilixResolutionError(name, resolutionStack);
}
const lifetime = resolver.lifetime || Lifetime.TRANSIENT;
// if we are running in strict mode, this resolver is not explicitly marked leak-safe, and any
// of the parents have a shorter lifetime than the one requested, throw an error.
if (options.strict && !resolver.isLeakSafe) {
const maybeLongerLifetimeParentIndex = resolutionStack.findIndex(({ lifetime: parentLifetime }) => isLifetimeLonger(parentLifetime, lifetime));
if (maybeLongerLifetimeParentIndex > -1) {
throw new AwilixResolutionError(name, resolutionStack, `Dependency '${name.toString()}' has a shorter lifetime than its ancestor: '${resolutionStack[maybeLongerLifetimeParentIndex].name.toString()}'`);
}
}
// Pushes the currently-resolving module information onto the stack
resolutionStack.push({ name, lifetime });
// Do the thing
let cached;
let resolved;
switch (lifetime) {
case Lifetime.TRANSIENT:
// Transient lifetime means resolve every time.
resolved = resolver.resolve(container);
break;
case Lifetime.SINGLETON:
// Singleton lifetime means cache at all times, regardless of scope.
cached = rootContainer.cache.get(name);
if (!cached) {
// if we are running in strict mode, perform singleton resolution using the root
// container only.
resolved = resolver.resolve(options.strict ? rootContainer : container);
rootContainer.cache.set(name, { resolver, value: resolved });
}
else {
resolved = cached.value;
}
break;
case Lifetime.SCOPED:
// Scoped lifetime means that the container
// that resolves the registration also caches it.
// If this container cache does not have it,
// resolve and cache it rather than using the parent
// container's cache.
cached = container.cache.get(name);
if (cached !== undefined) {
// We found one!
resolved = cached.value;
break;
}
// If we still have not found one, we need to resolve and cache it.
resolved = resolver.resolve(container);
container.cache.set(name, { resolver, value: resolved });
break;
default:
throw new AwilixResolutionError(name, resolutionStack, `Unknown lifetime "${resolver.lifetime}"`);
}
// Pop it from the stack again, ready for the next resolution
resolutionStack.pop();
return resolved;
}
catch (err) {
// When we get an error we need to reset the stack. Mutate the existing array rather than
// updating the reference to ensure all parent containers' stacks are also updated.
resolutionStack.length = 0;
throw err;
}
}
/**
* Checks if the registration with the given name exists.
*
* @param {string | symbol} name
* The name of the registration to resolve.
*
* @return {boolean}
* Whether or not the registration exists.
*/
function hasRegistration(name) {
return !!getRegistration(name);
}
/**
* Given a registration, class or function, builds it up and returns it.
* Does not cache it, this means that any lifetime configured in case of passing
* a registration will not be used.
*
* @param {Resolver|Constructor|Function} targetOrResolver
* @param {ResolverOptions} opts
*/
function build(targetOrResolver, opts) {
if (targetOrResolver && targetOrResolver.resolve) {
return targetOrResolver.resolve(container);
}
const funcName = 'build';
const paramName = 'targetOrResolver';
AwilixTypeError.assert(targetOrResolver, funcName, paramName, 'a registration, function or class', targetOrResolver);
AwilixTypeError.assert(typeof targetOrResolver === 'function', funcName, paramName, 'a function or class', targetOrResolver);
const resolver = isClass(targetOrResolver)
? asClass(targetOrResolver, opts)
: asFunction(targetOrResolver, opts);
return resolver.resolve(container);
}
/**
* Disposes this container and it's children, calling the disposer
* on all disposable registrations and clearing the cache.
*/
function dispose() {
const entries = Array.from(container.cache.entries());
container.cache.clear();
return Promise.all(entries.map(([, entry]) => {
const { resolver, value } = entry;
const disposable = resolver;
if (disposable.dispose) {
return Promise.resolve().then(() => disposable.dispose(value));
}
return Promise.resolve();
})).then(() => undefined);
}
}
exports.AwilixError = AwilixError;
exports.AwilixRegistrationError = AwilixRegistrationError;
exports.AwilixResolutionError = AwilixResolutionError;
exports.AwilixTypeError = AwilixTypeError;
exports.InjectionMode = InjectionMode;
exports.Lifetime = Lifetime;
exports.RESOLVER = RESOLVER;
exports.aliasTo = aliasTo;
exports.asClass = asClass;
exports.asFunction = asFunction;
exports.asValue = asValue;
exports.createBuildResolver = createBuildResolver;
exports.createContainer = createContainer;
exports.createDisposableResolver = createDisposableResolver;
exports.AwilixError = AwilixError;
exports.AwilixRegistrationError = AwilixRegistrationError;
exports.AwilixResolutionError = AwilixResolutionError;
exports.AwilixTypeError = AwilixTypeError;
exports.InjectionMode = InjectionMode;
exports.Lifetime = Lifetime;
exports.RESOLVER = RESOLVER;
exports.aliasTo = aliasTo;
exports.asClass = asClass;
exports.asFunction = asFunction;
exports.asValue = asValue;
exports.createBuildResolver = createBuildResolver;
exports.createContainer = createContainer;
exports.createDisposableResolver = createDisposableResolver;
exports.isClass = isClass;
exports.isFunction = isFunction;
exports.listModules = listModules;
}));

@@ -50,3 +50,3 @@ import { Constructor } from './resolvers';

*/
export declare function isFunction(val: unknown): boolean;
export declare function isFunction(val: unknown): val is Function;
/**

@@ -53,0 +53,0 @@ * Returns the unique items in the array.

@@ -93,2 +93,3 @@ "use strict";

*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
function isFunction(val) {

@@ -95,0 +96,0 @@ return typeof val === 'function';

{
"name": "awilix",
"version": "11.0.4",
"version": "12.0.0",
"description": "Extremely powerful dependency injection container.",

@@ -15,2 +15,21 @@ "main": "lib/awilix.js",

},
"exports": {
".": {
"import": "./lib/awilix.module.mjs",
"types": "./lib/awilix.d.ts",
"default": "./lib/awilix.js"
},
"./browser": {
"import": "./lib/awilix.browser.js",
"types": "./lib/awilix.d.ts",
"default": "./lib/awilix.browser.js"
},
"./lib/*.js": {
"types": "./lib/*.d.ts",
"default": "./lib/*.js"
},
"./lib/*": {
"default": "./lib/*.js"
}
},
"scripts": {

@@ -53,20 +72,20 @@ "build": "rimraf lib && tsc -p tsconfig.build.json && rollup -c",

"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/plugin-transform-runtime": "^7.25.4",
"@babel/preset-env": "^7.25.4",
"@babel/runtime": "^7.25.4",
"@types/jest": "^29.5.12",
"@types/node": "^22.5.0",
"@babel/core": "^7.25.7",
"@babel/plugin-transform-runtime": "^7.25.7",
"@babel/preset-env": "^7.25.7",
"@babel/runtime": "^7.25.7",
"@rollup/plugin-commonjs": "^28.0.0",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-replace": "^6.0.1",
"@types/jest": "^29.5.13",
"@types/node": "^22.7.4",
"babel-jest": "^29.7.0",
"eslint": "^9.9.1",
"husky": "^9.1.5",
"eslint": "^9.12.0",
"husky": "^9.1.6",
"jest": "^29.7.0",
"lint-staged": "^15.2.9",
"lint-staged": "^15.2.10",
"prettier": "^3.3.3",
"rimraf": "^6.0.1",
"rollup": "^4.21.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup": "^4.24.0",
"rollup-plugin-copy": "^3.5.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-typescript2": "^0.36.0",

@@ -76,4 +95,4 @@ "smid": "^0.1.1",

"tslib": "^2.7.0",
"typescript": "^5.5.4",
"typescript-eslint": "^8.2.0"
"typescript": "^5.6.2",
"typescript-eslint": "^8.8.0"
},

@@ -80,0 +99,0 @@ "dependencies": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc