@teqfw/di 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/di.esm.js CHANGED
@@ -30,113 +30,113 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _src
30
30
 
31
31
  /***/ }),
32
32
 
33
- /***/ "./src/Api/ObjectKey.js":
34
- /*!******************************!*\
35
- !*** ./src/Api/ObjectKey.js ***!
36
- \******************************/
33
+ /***/ "./src/Container.js":
34
+ /*!**************************!*\
35
+ !*** ./src/Container.js ***!
36
+ \**************************/
37
37
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
38
38
 
39
39
  "use strict";
40
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Api_ObjectKey)\n/* harmony export */ });\n/**\n * This is a DTO that represents the structure of an ID for a runtime dependency.\n */\nclass TeqFw_Di_Api_ObjectKey {\n /**\n * The name of an export of the module.\n * @type {string}\n */\n exportName;\n /**\n * Composition type (see Defs.COMPOSE_): use the export as Factory (F) or return as-is (A).\n * @type {string}\n */\n composition;\n /**\n * Lifestyle type (see Defs.LIFE_): singleton (S) or instance (I).\n * @type {string}\n */\n life;\n /**\n * The code for ES6 module that can be converted to the path to this es6 module.\n * @type {string}\n */\n moduleName;\n /**\n * Object key value.\n * @type {string}\n */\n value;\n /**\n * List of wrappers to decorate the result.\n * @type {string[]}\n */\n wrappers = [];\n}\n\n//# sourceURL=webpack://@teqfw/di/./src/Api/ObjectKey.js?");
40
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Container)\n/* harmony export */ });\n/* harmony import */ var _Container_A_Composer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Container/A/Composer.js */ \"./src/Container/A/Composer.js\");\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Defs.js */ \"./src/Defs.js\");\n/* harmony import */ var _Container_Parser_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Container/Parser.js */ \"./src/Container/Parser.js\");\n/* harmony import */ var _Container_PreProcessor_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Container/PreProcessor.js */ \"./src/Container/PreProcessor.js\");\n/* harmony import */ var _Container_PostProcessor_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Container/PostProcessor.js */ \"./src/Container/PostProcessor.js\");\n/* harmony import */ var _Container_Resolver_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Container/Resolver.js */ \"./src/Container/Resolver.js\");\n/**\n * The Object Container (composition root).\n * @namespace TeqFw_Di_Container\n */\n\n\n\n\n\n\n\n// FUNCS\n/**\n * ID to store singletons in the internal registry.\n * @param {TeqFw_Di_DepId} key\n * @return {string}\n */\nfunction getSingletonId(key) {\n return `${key.moduleName}#${key.exportName}`;\n}\n\n// MAIN\n/**\n * @implements TeqFw_Di_Api_Container\n */\nclass TeqFw_Di_Container {\n\n constructor() {\n // VARS\n let _composer = new _Container_A_Composer_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n let _debug = false;\n let _parser = new _Container_Parser_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]();\n let _preProcessor = new _Container_PreProcessor_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n let _postProcessor = new _Container_PostProcessor_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]();\n\n /**\n * Registry for paths for loaded es6 modules.\n *\n * @type {Object<string, string>}\n */\n const _regPaths = {};\n /**\n * Registry to store singletons.\n * @type {Object<string, *>}\n */\n const _regSingles = {};\n let _resolver = new _Container_Resolver_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"]();\n\n // FUNCS\n\n function log() {\n if (_debug) console.log(...arguments);\n }\n\n // INSTANCE METHODS\n\n this.get = async function (runtimeDepId) {\n return this.compose(runtimeDepId, []);\n };\n\n /**\n * This method is 'private' for the npm package. It is used in the Composer only.\n *\n * @param {string} depId runtime dependency ID\n * @param {string[]} stack set of the depId to detect circular dependencies\n * @return {Promise<*>}\n */\n this.compose = async function (depId, stack = []) {\n log(`Object '${depId}' is requested.`);\n // return container itself if requested\n if (\n (depId === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].KEY_CONTAINER) ||\n (depId === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].KEY_CONTAINER_NS)\n ) {\n log(`Container itself is returned.`);\n return _regSingles[_Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].KEY_CONTAINER];\n }\n // parse the `objectKey` and get the structured DTO\n const parsed = _parser.parse(depId);\n // modify original key according to some rules (replacements, etc.)\n const key = _preProcessor.modify(parsed, stack);\n // return existing singleton\n if (key.life === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON) {\n const singleId = getSingletonId(key);\n if (_regSingles[singleId]) {\n log(`Existing singleton '${singleId}' is returned.`);\n return _regSingles[singleId];\n }\n }\n // resolve path to es6 module if not resolved before\n if (!_regPaths[key.moduleName]) {\n log(`ES6 module '${key.moduleName}' is not resolved yet`);\n // convert module name to the path to es6-module file with a sources\n _regPaths[key.moduleName] = _resolver.resolve(key.moduleName);\n }\n\n // load es6 module\n let module;\n const path = _regPaths[key.moduleName];\n try {\n module = await __webpack_require__(\"./src lazy recursive\")(path);\n log(`ES6 module '${key.moduleName}' is loaded from '${path}'.`);\n } catch (e) {\n console.error(\n e?.message,\n `Object key: \"${depId}\".`,\n `Path: \"${path}\".`,\n `Stack: ${JSON.stringify(stack)}`\n );\n throw e;\n }\n // create object using the composer then modify it in post-processor\n let res = await _composer.create(key, module, stack, this);\n res = await _postProcessor.modify(res, key, stack);\n log(`Object '${depId}' is created.`);\n\n // save singletons\n if (key.life === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON) {\n const singleId = getSingletonId(key);\n _regSingles[singleId] = res;\n log(`Object '${depId}' is saved as singleton.`);\n }\n return res;\n };\n\n this.getParser = () => _parser;\n\n this.getPreProcessor = () => _preProcessor;\n\n this.getPostProcessor = () => _postProcessor;\n this.getResolver = () => _resolver;\n\n this.setDebug = function (data) {\n _debug = data;\n _composer.setDebug(data);\n };\n\n this.setParser = (data) => _parser = data;\n\n this.setPreProcessor = (data) => _preProcessor = data;\n\n this.setPostProcessor = (data) => _postProcessor = data;\n\n this.setResolver = (data) => _resolver = data;\n\n // MAIN\n _regSingles[_Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].KEY_CONTAINER] = this;\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Container.js?");
41
41
 
42
42
  /***/ }),
43
43
 
44
- /***/ "./src/Composer.js":
45
- /*!*************************!*\
46
- !*** ./src/Composer.js ***!
47
- \*************************/
44
+ /***/ "./src/Container/A/Composer.js":
45
+ /*!*************************************!*\
46
+ !*** ./src/Container/A/Composer.js ***!
47
+ \*************************************/
48
48
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
49
49
 
50
50
  "use strict";
51
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Composer)\n/* harmony export */ });\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Defs.js */ \"./src/Defs.js\");\n/* harmony import */ var _SpecAnalyser_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./SpecAnalyser.js */ \"./src/SpecAnalyser.js\");\n/**\n *\n */\n\n\n\n// FUNCS\n\n// MAIN\nclass TeqFw_Di_Composer {\n\n constructor() {\n // VARS\n let _debug = false;\n\n // FUNCS\n function log(msg) {\n if (_debug) console.log(msg);\n }\n\n // INSTANCE METHODS\n\n /**\n *\n * @param {TeqFw_Di_Api_ObjectKey} key\n * @param {Object} module\n * @param {string[]} stack array of the parent objects to prevent dependency loop\n * @param {TeqFw_Di_Container} container\n * @return {Promise<*>}\n */\n this.create = async function (key, module, stack, container) {\n if (stack.includes(key.value))\n throw new Error(`Circular dependency for '${key.value}'. Parents are: ${JSON.stringify(stack)}`);\n if (key.exportName) {\n // use export from the es6-module\n const stackNew = [...stack, key.value];\n const {[key.exportName]: exp} = module;\n if (key.composition === _Defs_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].COMPOSE_FACTORY) {\n if (typeof exp === 'function') {\n // create deps for factory function\n const deps = (0,_SpecAnalyser_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(exp);\n if (deps.length) log(`Deps for object '${key.value}' are: ${JSON.stringify(deps)}`);\n const spec = {};\n for (const dep of deps)\n spec[dep] = await container.get(dep, stackNew);\n // create a new object with the factory function\n const res = (_Defs_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].isClass(exp)) ? new exp(spec) : exp(spec);\n if (res instanceof Promise)\n return await res;\n else\n return res;\n } else\n // just clone the export\n return Object.assign({}, exp);\n } else\n return exp;\n } else {\n return module;\n }\n };\n\n this.setDebug = function (data) {\n _debug = data;\n };\n\n // MAIN\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Composer.js?");
51
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Container_A_Composer)\n/* harmony export */ });\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../Defs.js */ \"./src/Defs.js\");\n/* harmony import */ var _Composer_A_SpecParser_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Composer/A/SpecParser.js */ \"./src/Container/A/Composer/A/SpecParser.js\");\n/**\n * The composer creates requested objects. It uses the container to create dependencies.\n *\n * @namespace TeqFw_Di_Container_A_Composer\n */\n\n\n\nclass TeqFw_Di_Container_A_Composer {\n\n constructor() {\n // VARS\n let _debug = false;\n\n // FUNCS\n function log(msg) {\n if (_debug) console.log(msg);\n }\n\n // INSTANCE METHODS\n\n /**\n * Returns or creates and returns the requested object.\n *\n * @param {TeqFw_Di_DepId} depId\n * @param {Object} module - imported es6 module\n * @param {string[]} stack - array of the parent objects IDs to prevent dependency loop\n * @param {TeqFw_Di_Container} container - to create dependencies for requested object\n * @return {Promise<*>}\n */\n this.create = async function (depId, module, stack, container) {\n if (stack.includes(depId.value))\n throw new Error(`Circular dependency for '${depId.value}'. Parents are: ${JSON.stringify(stack)}`);\n if (depId.exportName) {\n // use export from the es6-module\n const stackNew = [...stack, depId.value];\n const {[depId.exportName]: exp} = module;\n if (depId.composition === _Defs_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].COMPOSE_FACTORY) {\n if (typeof exp === 'function') {\n // create deps for factory function\n const deps = (0,_Composer_A_SpecParser_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(exp);\n if (deps.length) log(`Deps for object '${depId.value}' are: ${JSON.stringify(deps)}`);\n const spec = {};\n for (const dep of deps)\n spec[dep] = await container.compose(dep, stackNew);\n // create a new object with the factory function\n const res = (_Defs_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].isClass(exp)) ? new exp(spec) : exp(spec);\n if (res instanceof Promise)\n return await res;\n else\n return res;\n } else\n // just clone the export\n return Object.assign({}, exp);\n } else\n // just return the export (w/o factory function)\n return exp;\n } else {\n // TODO: this is almost useless option\n return module;\n }\n };\n\n this.setDebug = function (data) {\n _debug = data;\n };\n\n // MAIN\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Container/A/Composer.js?");
52
52
 
53
53
  /***/ }),
54
54
 
55
- /***/ "./src/Container.js":
56
- /*!**************************!*\
57
- !*** ./src/Container.js ***!
58
- \**************************/
55
+ /***/ "./src/Container/A/Composer/A/SpecParser.js":
56
+ /*!**************************************************!*\
57
+ !*** ./src/Container/A/Composer/A/SpecParser.js ***!
58
+ \**************************************************/
59
59
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
60
60
 
61
61
  "use strict";
62
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Container)\n/* harmony export */ });\n/* harmony import */ var _Composer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Composer.js */ \"./src/Composer.js\");\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Defs.js */ \"./src/Defs.js\");\n/* harmony import */ var _Parser_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Parser.js */ \"./src/Parser.js\");\n/* harmony import */ var _PreProcessor_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./PreProcessor.js */ \"./src/PreProcessor.js\");\n/* harmony import */ var _PreProcessor_Replace_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PreProcessor/Replace.js */ \"./src/PreProcessor/Replace.js\");\n/* harmony import */ var _Resolver_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Resolver.js */ \"./src/Resolver.js\");\n/**\n * The Object Container (composition root).\n */\n\n\n\n\n\n\n\n// VARS\n\n// FUNCS\n/**\n * ID to store singletons in the internal registry.\n * @param {TeqFw_Di_Api_ObjectKey} key\n * @return {string}\n */\nfunction getSingletonId(key) {\n return `${key.moduleName}#${key.exportName}`;\n}\n\n// MAIN\nclass TeqFw_Di_Container {\n\n constructor() {\n // VARS\n let _composer = new _Composer_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n let _debug = false;\n let _parser = new _Parser_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]();\n let _preProcessor = new _PreProcessor_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n _preProcessor.addHandler((0,_PreProcessor_Replace_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"])()); // create new instance of the replacement handler\n\n /**\n * Registry for loaded es6 modules.\n * @type {Object<string, Module>}\n */\n const _regModules = {};\n /**\n * Registry to store singletons.\n * @type {Object<string, *>}\n */\n const _regSingles = {};\n let _resolver = new _Resolver_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"]();\n\n // FUNCS\n function error() {\n console.error(...arguments);\n }\n\n function log() {\n if (_debug) console.log(...arguments);\n }\n\n\n // INSTANCE METHODS\n\n this.get = async function (objectKey, stack = []) {\n log(`Object '${objectKey}' is requested.`);\n // return container itself if requested\n if (\n (objectKey === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].KEY_CONTAINER) ||\n (objectKey === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].KEY_CONTAINER_NS)\n ) {\n log(`Container itself is returned.`);\n return _regSingles[_Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].KEY_CONTAINER];\n }\n // parse the `objectKey` and get the structured DTO\n const parsed = _parser.parse(objectKey);\n // modify original key according to some rules (replacements, etc.)\n const key = _preProcessor.process(parsed);\n // return existing singleton\n if (key.life === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON) {\n const singleId = getSingletonId(key);\n if (_regSingles[singleId]) {\n log(`Existing singleton '${singleId}' is returned.`);\n return _regSingles[singleId];\n }\n }\n // load es6 module if not loaded before\n if (!_regModules[key.moduleName]) {\n log(`ES6 module '${key.moduleName}' is not loaded yet`);\n // convert module name to the path to es6-module file with a sources\n const path = _resolver.resolve(key.moduleName);\n try {\n _regModules[key.moduleName] = await __webpack_require__(\"./src lazy recursive\")(path);\n log(`ES6 module '${key.moduleName}' is loaded from '${path}'.`);\n } catch (e) {\n console.error(\n e?.message,\n `Object key: \"${objectKey}\".`,\n `Path: \"${path}\".`,\n `Stack: ${JSON.stringify(stack)}`\n );\n throw e;\n }\n\n }\n // create object using the composer\n let res = await _composer.create(key, _regModules[key.moduleName], stack, this);\n log(`Object '${objectKey}' is created.`);\n\n // TODO: refactor this code to use wrappers w/o hardcode\n if (key.wrappers.includes(_Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].WRAP_PROXY)) {\n const me = this;\n res = new Proxy({dep: undefined, objectKey}, {\n get: async function (base, name) {\n if (name === 'create') base.dep = await me.get(base.objectKey);\n return base.dep;\n }\n });\n }\n\n if (key.life === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON) {\n const singleId = getSingletonId(key);\n _regSingles[singleId] = res;\n log(`Object '${objectKey}' is saved as singleton.`);\n }\n return res;\n };\n\n this.getParser = () => _parser;\n\n this.getPreProcessor = () => _preProcessor\n ;\n this.getResolver = () => _resolver;\n\n this.setDebug = function (data) {\n _debug = data;\n _composer.setDebug(data);\n };\n\n this.setParser = (data) => _parser = data;\n\n this.setPreProcessor = (data) => _preProcessor = data;\n\n this.setResolver = (data) => _resolver = data;\n\n // MAIN\n _regSingles[_Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].KEY_CONTAINER] = this;\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Container.js?");
62
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../Defs.js */ \"./src/Defs.js\");\n/**\n * This function analyses specification of dependencies extracted from the text definition of the function itself.\n *\n * This is a local module and is used only inside the `TeqFw_Di_Container_A_Composer` space.\n *\n * @namespace TeqFw_Di_Container_A_Composer_A_SpecParser\n */\n\n\n// VARS\nconst FUNC = /(function)*\\s*\\w*\\s*\\(\\s*\\{([^\\}]*)\\}/s;\nconst CLASS = /constructor\\s*\\(\\s*\\{([^\\}]*)\\}/s;\n\n// FUNCS\n\n/**\n * Internal function to analyze extracted parameters.\n *\n * @param {string} params\n * @return {string[]}\n * @private\n */\nfunction _analyze(params) {\n const res = [];\n // create wrapper for arguments and collect dependencies using Proxy\n try {\n const fn = new Function(`{${params}}`, 'return');\n const spec = new Proxy({}, {\n get: (target, prop) => res.push(prop),\n });\n // run wrapper and return dependencies\n fn(spec);\n } catch (e) {\n const msg = `Cannot analyze the deps specification:${params}\\n`\n + `\\nPlease, be sure that spec does not contain extra ')' in a comments.`\n + `\\n\\nError: ${e}`;\n throw new Error(msg);\n }\n return res;\n}\n\n/**\n * @param {Function|Object} exp\n * @return {string[]}\n */\nfunction _analyzeClass(exp) {\n const res = [];\n // extract arguments from constructor\n const def = exp.toString();\n const parts = CLASS.exec(def);\n if (parts) {\n res.push(..._analyze(parts[1]));\n } // else: constructor does not have arguments\n return res;\n}\n\n/**\n * @param {Function|Object} exp\n * @return {string[]}\n */\nfunction _analyzeFunc(exp) {\n const res = [];\n // extract arguments from factory function\n const def = exp.toString();\n const parts = FUNC.exec(def);\n if (parts) {\n res.push(..._analyze(parts[2]));\n } // else: constructor does not have arguments\n return res;\n}\n\n// MAIN\n/**\n * @param {Function|Object} exp\n * @return {string[]}\n */\n/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(exp) {\n if (typeof exp === 'function') {\n if (_Defs_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].isClass(exp)) {\n return _analyzeClass(exp);\n } else {\n return _analyzeFunc(exp);\n }\n } else\n return [];\n}\n\n//# sourceURL=webpack://@teqfw/di/./src/Container/A/Composer/A/SpecParser.js?");
63
63
 
64
64
  /***/ }),
65
65
 
66
- /***/ "./src/Defs.js":
67
- /*!*********************!*\
68
- !*** ./src/Defs.js ***!
69
- \*********************/
66
+ /***/ "./src/Container/A/Parser/Chunk/Def.js":
67
+ /*!*********************************************!*\
68
+ !*** ./src/Container/A/Parser/Chunk/Def.js ***!
69
+ \*********************************************/
70
70
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
71
71
 
72
72
  "use strict";
73
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/**\n * Hardcoded constants for the package.\n */\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n COMPOSE_AS_IS: 'A',\n COMPOSE_FACTORY: 'F',\n EXT: 'js',\n KEY_CONTAINER: 'container',\n KEY_CONTAINER_NS: 'TeqFw_Di_Container$',\n LIFE_INSTANCE: 'I',\n LIFE_SINGLETON: 'S',\n WRAP_PROXY: 'proxy',\n\n /**\n * Return 'true' if function is a class definition.\n * See: https://stackoverflow.com/a/29094018/4073821\n *\n * @param {function} fn\n * @return {boolean}\n */\n isClass(fn) {\n const proto = Object.getOwnPropertyDescriptor(fn, 'prototype');\n return proto && !proto.writable;\n },\n});\n\n//# sourceURL=webpack://@teqfw/di/./src/Defs.js?");
73
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Container_A_Parser_Chunk_Def)\n/* harmony export */ });\n/* harmony import */ var _DepId_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../DepId.js */ \"./src/DepId.js\");\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../Defs.js */ \"./src/Defs.js\");\n/**\n * Default parser for object keys in format:\n * - Vnd_Pkg_Prj_Mod$FA\n *\n * @namespace TeqFw_Di_Container_A_Parser_Chunk_Def\n */\n\n\n\n// VARS\n/** @type {RegExp} expression for default object key (Ns_Module[.|#]export$[F|A][S|I]) */\nconst REGEXP = /^((([A-Z])[A-Za-z0-9_]*)((#|\\.)?([A-Za-z0-9]*)((\\$)([F|A])?([S|I])?)?)?)$/;\n\n/**\n * @implements TeqFw_Di_Api_Container_Parser_Chunk\n */\nclass TeqFw_Di_Container_A_Parser_Chunk_Def {\n\n canParse(depId) {\n // default parser always trys to parse the depId\n return true;\n }\n\n parse(objectKey) {\n const res = new _DepId_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n res.value = objectKey;\n const parts = REGEXP.exec(objectKey);\n if (parts) {\n res.moduleName = parts[2];\n if (parts[5] === '.') {\n // App_Service.export...\n if (parts[8] === '$') {\n // App_Service.export$...\n res.composition = _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY;\n res.exportName = parts[6];\n res.life = (parts[10] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE)\n ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON;\n } else {\n res.composition = ((parts[8] === undefined) || (parts[8] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS))\n ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY;\n res.exportName = parts[6];\n res.life = ((parts[8] === undefined) || (parts[10] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON))\n ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE;\n }\n\n\n } else if (parts[8] === '$') {\n // App_Logger$FS\n res.composition = ((parts[9] === undefined) || (parts[9] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY))\n ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS;\n res.exportName = 'default';\n if (parts[10]) {\n res.life = (parts[10] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON) ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE;\n } else {\n res.life = (res.composition === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY) ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE;\n }\n } else {\n // App_Service\n res.composition = _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS;\n res.exportName = 'default';\n res.life = _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON;\n }\n }\n\n // we should always use singletons for as-is exports\n if ((res.composition === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS) && (res.life === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE))\n throw new Error(`Export is not a function and should be used as a singleton only: '${res.value}'.`);\n return res;\n }\n}\n\n//# sourceURL=webpack://@teqfw/di/./src/Container/A/Parser/Chunk/Def.js?");
74
74
 
75
75
  /***/ }),
76
76
 
77
- /***/ "./src/Parser.js":
78
- /*!***********************!*\
79
- !*** ./src/Parser.js ***!
80
- \***********************/
77
+ /***/ "./src/Container/Parser.js":
78
+ /*!*********************************!*\
79
+ !*** ./src/Container/Parser.js ***!
80
+ \*********************************/
81
81
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
82
82
 
83
83
  "use strict";
84
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Parser)\n/* harmony export */ });\n/* harmony import */ var _Parser_Def_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Parser/Def.js */ \"./src/Parser/Def.js\");\n/**\n * The root parser for `objectKeys` contains all other parsers.\n * It calls the other parser one by one to parse the object key as a structure.\n * Every npm package can have its own format for an `objectKey`.\n */\n\n\n// VARS\nconst KEY_PARSER = 'parser';\nconst KEY_VALIDATOR = 'validator';\n\n// MAIN\nclass TeqFw_Di_Parser {\n\n constructor() {\n // VARS\n /**\n * Default parsing function.\n * @type {(function(string): TeqFw_Di_Api_ObjectKey)}\n */\n let _defaultParser = _Parser_Def_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\n /**\n * The array of the pairs {validator, parser} to parse objectKeys.\n * @type {Object<validator:function, parser:function>[]}\n */\n const _parsers = [];\n\n // INSTANCE METHODS\n\n /**\n *\n * @param {function(string):boolean} validator\n * @param {function(string):TeqFw_Di_Api_ObjectKey} parser\n */\n this.addParser = function (validator, parser) {\n _parsers.push({[KEY_VALIDATOR]: validator, [KEY_PARSER]: parser});\n };\n\n /**\n * @param {string} objectKey\n * @return {TeqFw_Di_Api_ObjectKey}\n */\n this.parse = function (objectKey) {\n let res;\n for (const one of _parsers) {\n if (one[KEY_VALIDATOR](objectKey)) {\n res = one[KEY_PARSER](objectKey);\n break;\n }\n }\n if (!res)\n res = _defaultParser(objectKey);\n return res;\n };\n\n /**\n * @param {function(string):TeqFw_Di_Api_ObjectKey} parser\n */\n this.setDefaultParser = function (parser) {\n _defaultParser = parser;\n };\n\n // MAIN\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Parser.js?");
84
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Container_Parser)\n/* harmony export */ });\n/* harmony import */ var _A_Parser_Chunk_Def_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./A/Parser/Chunk/Def.js */ \"./src/Container/A/Parser/Chunk/Def.js\");\n/**\n * The parser for the runtime dependency ID contains multiple chunks. Each npm package can have its own format for\n * a `depId`. The parser calls the chunks one by one to parse the string ID as a structure and returns the first result.\n * If none of the chunks processed the `depId`, the parser calls the default chunk.\n */\n\n\n/**\n * @implements TeqFw_Di_Api_Container_Parser\n */\nclass TeqFw_Di_Container_Parser {\n constructor() {\n // VARS\n /**\n * The default chunk to parse the depId if no other chunks have parsed this depId.\n *\n * @type {TeqFw_Di_Api_Container_Parser_Chunk}\n */\n let _defaultChunk = new _A_Parser_Chunk_Def_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n /**\n * The array of the chunks to parse dependency IDs.\n * @type {TeqFw_Di_Api_Container_Parser_Chunk[]}\n */\n const _chunks = [];\n\n // INSTANCE METHODS\n\n this.addChunk = function (chunk) {\n _chunks.push(chunk);\n };\n\n this.parse = function (depId) {\n let res;\n for (const one of _chunks)\n if (one.canParse(depId)) {\n res = one.parse(depId);\n break;\n }\n if (!res)\n res = _defaultChunk?.parse(depId);\n return res;\n };\n\n this.setDefaultChunk = function (chunk) {\n _defaultChunk = chunk;\n };\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Container/Parser.js?");
85
85
 
86
86
  /***/ }),
87
87
 
88
- /***/ "./src/Parser/Def.js":
89
- /*!***************************!*\
90
- !*** ./src/Parser/Def.js ***!
91
- \***************************/
88
+ /***/ "./src/Container/PostProcessor.js":
89
+ /*!****************************************!*\
90
+ !*** ./src/Container/PostProcessor.js ***!
91
+ \****************************************/
92
92
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
93
93
 
94
94
  "use strict";
95
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Parser_Def)\n/* harmony export */ });\n/* harmony import */ var _Api_ObjectKey_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Api/ObjectKey.js */ \"./src/Api/ObjectKey.js\");\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Defs.js */ \"./src/Defs.js\");\n/**\n * Default parser for object keys in format:\n * - Vnd_Pkg_Prj_Mod$FA\n */\n\n\n\n// VARS\n/** @type {RegExp} expression for default object key (Ns_Module[.|#]export$[F|A][S|I]) */\nconst REGEXP = /^((([A-Z])[A-Za-z0-9_]*)((#|\\.)?([A-Za-z0-9]*)((\\$)([F|A])?([S|I])?)?)?)$/;\n\n\n// MAIN\n/**\n * @param {string} objectKey\n * @return {TeqFw_Di_Api_ObjectKey}\n */\nfunction TeqFw_Di_Parser_Def(objectKey) {\n const res = new _Api_ObjectKey_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n res.value = objectKey;\n const parts = REGEXP.exec(objectKey);\n if (parts) {\n res.moduleName = parts[2];\n if (parts[5] === '.') {\n // App_Service.export...\n if (parts[8] === '$') {\n // App_Service.export$...\n res.composition = _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY;\n res.exportName = parts[6];\n res.life = (parts[10] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE)\n ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON;\n } else {\n res.composition = ((parts[8] === undefined) || (parts[8] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS))\n ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY;\n res.exportName = parts[6];\n res.life = ((parts[8] === undefined) || (parts[10] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON))\n ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE;\n }\n\n\n } else if (parts[8] === '$') {\n // App_Logger$FS\n res.composition = ((parts[9] === undefined) || (parts[9] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY))\n ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS;\n res.exportName = 'default';\n if (parts[10]) {\n res.life = (parts[10] === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON) ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE;\n } else {\n res.life = (res.composition === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_FACTORY) ? _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON : _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE;\n }\n } else {\n // App_Service\n res.composition = _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS;\n res.exportName = 'default';\n res.life = _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_SINGLETON;\n }\n }\n\n // we should always use singletons for as-is exports\n if ((res.composition === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].COMPOSE_AS_IS) && (res.life === _Defs_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].LIFE_INSTANCE))\n throw new Error(`Export is not a function and should be used as a singleton only: '${res.value}'.`);\n return res;\n}\n\n//# sourceURL=webpack://@teqfw/di/./src/Parser/Def.js?");
95
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Container_PostProcessor)\n/* harmony export */ });\n/**\n * The post-processor handles the result object after composition and before returning.\n *\n * @implements TeqFw_Di_Api_Container_PostProcessor\n */\nclass TeqFw_Di_Container_PostProcessor {\n\n constructor() {\n // VARS\n\n /**\n * The array of the chunks to modify dependency IDs.\n * @type {TeqFw_Di_Api_Container_PostProcessor_Chunk[]}\n */\n const _chunks = [];\n\n // INSTANCE METHODS\n\n this.addChunk = function (chunk) {\n _chunks.push(chunk);\n };\n\n this.modify = async function (obj, depId, stack) {\n let res = obj;\n for (const one of _chunks) {\n res = one.modify(res, depId, stack);\n if (res instanceof Promise) res = await res;\n }\n return res;\n };\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Container/PostProcessor.js?");
96
96
 
97
97
  /***/ }),
98
98
 
99
- /***/ "./src/PreProcessor.js":
100
- /*!*****************************!*\
101
- !*** ./src/PreProcessor.js ***!
102
- \*****************************/
99
+ /***/ "./src/Container/PreProcessor.js":
100
+ /*!***************************************!*\
101
+ !*** ./src/Container/PreProcessor.js ***!
102
+ \***************************************/
103
103
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
104
104
 
105
105
  "use strict";
106
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_PreProcessor)\n/* harmony export */ });\n/**\n * The preprocessor handles object keys after the parsing but before creating any objects.\n * A replacement rules can be implemented here.\n * Every handler is a function with 2 arguments:\n * - objectKey: current key after processing with other handlers;\n * - originalKey: the key before any processing;\n */\nclass TeqFw_Di_PreProcessor {\n\n constructor() {\n // VARS\n /**\n * The array of handlers in the dependency order (from the basic (di) up to the app).\n * @type {Array<function(TeqFw_Di_Api_ObjectKey, TeqFw_Di_Api_ObjectKey):TeqFw_Di_Api_ObjectKey>}\n */\n const _handlers = [];\n\n // INSTANCE METHODS\n\n /**\n *\n * @param {function(TeqFw_Di_Api_ObjectKey, TeqFw_Di_Api_ObjectKey):TeqFw_Di_Api_ObjectKey} hndl\n */\n this.addHandler = function (hndl) {\n _handlers.push(hndl);\n };\n\n /**\n * Get all pre-processing handlers.\n * @return {Array<function(TeqFw_Di_Api_ObjectKey, TeqFw_Di_Api_ObjectKey): TeqFw_Di_Api_ObjectKey>}\n */\n this.getHandlers = () => _handlers;\n\n /**\n * @param {TeqFw_Di_Api_ObjectKey} objectKey\n * @return {TeqFw_Di_Api_ObjectKey}\n */\n this.process = function (objectKey) {\n let res = objectKey;\n for (const one of _handlers)\n res = one(res, objectKey);\n return res;\n };\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/PreProcessor.js?");
106
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Container_PreProcessor)\n/* harmony export */ });\n/**\n * The preprocessor handles object keys after the parsing but before creating any objects.\n * A replacement rules can be implemented here.\n * Every handler is a function with 2 arguments:\n * - objectKey: current key after processing with other handlers;\n * - originalKey: the key before any processing;\n *\n * @implements TeqFw_Di_Api_Container_PreProcessor\n */\nclass TeqFw_Di_Container_PreProcessor {\n\n constructor() {\n // VARS\n\n /**\n * The array of the chunks to modify dependency IDs.\n * @type {TeqFw_Di_Api_Container_PreProcessor_Chunk[]}\n */\n const _chunks = [];\n\n // INSTANCE METHODS\n\n this.addChunk = function (chunk) {\n _chunks.push(chunk);\n };\n\n this.modify = function (depId, stack) {\n let res = depId;\n for (const one of _chunks)\n res = one.modify(res, depId, stack);\n return res;\n };\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Container/PreProcessor.js?");
107
107
 
108
108
  /***/ }),
109
109
 
110
- /***/ "./src/PreProcessor/Replace.js":
111
- /*!*************************************!*\
112
- !*** ./src/PreProcessor/Replace.js ***!
113
- \*************************************/
110
+ /***/ "./src/Container/Resolver.js":
111
+ /*!***********************************!*\
112
+ !*** ./src/Container/Resolver.js ***!
113
+ \***********************************/
114
114
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
115
115
 
116
116
  "use strict";
117
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/**\n * Pre-processor handler to replace one object key with another.\n */\n\n/**\n * Factory function to create pre-processor handler.\n * @return {function(*): *}\n */\n/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__() {\n // VARS\n /**\n * Storage for ES modules replacements (interface => implementation).\n * Sample: {['Vnd_Plug_Interface']:'Vnd_Plug_Impl', ...}\n * @type {Object<string, string>}\n */\n const replacements = {};\n\n // FUNCS\n /**\n * @param {TeqFw_Di_Api_ObjectKey} objectKey\n * @param {TeqFw_Di_Api_ObjectKey} originalKey\n * @return {TeqFw_Di_Api_ObjectKey}\n * @namespace\n */\n function TeqFw_Di_PreProcessor_Replace(objectKey, originalKey) {\n let module = objectKey.moduleName;\n while (replacements[module]) module = replacements[module];\n if (module !== objectKey.moduleName) {\n const res = Object.assign({}, objectKey);\n res.moduleName = module;\n return res;\n } else\n return objectKey;\n }\n\n /**\n * Add replacement for ES6 modules.\n *\n * @param {string} orig ('Vnd_Plug_Interface')\n * @param {string} alter ('Vnd_Plug_Impl')\n */\n TeqFw_Di_PreProcessor_Replace.add = function (orig, alter) {\n replacements[orig] = alter;\n };\n\n // MAIN\n return TeqFw_Di_PreProcessor_Replace;\n}\n\n//# sourceURL=webpack://@teqfw/di/./src/PreProcessor/Replace.js?");
117
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Container_Resolver)\n/* harmony export */ });\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Defs.js */ \"./src/Defs.js\");\n/**\n * The Resolver should convert ES6 module name into the path to the sources (file path or URL).\n *\n * This is a base resolver that considers that:\n * - module name is Zend1-compatible ('Vendor_Package_Module')\n * - every namespace is bound to some real path ('Vendor_Package_' => '.../node_modules/@vendor/package/src/...)\n * - every package has sources with the same extensions (*.js, *.mjs, *.es6, ...)\n * - namespaces can be nested (App_Web_ => ./@app/web/..., App_Web_Api_ => ./@app/web_api/...)\n */\n\n\n// VARS\nconst KEY_EXT = 'ext';\nconst KEY_NS = 'ns';\nconst KEY_PATH = 'root';\n/**\n * Namespace parts separator.\n *\n * @type {string}\n */\nconst NSS = '_';\n\n// MAIN\nclass TeqFw_Di_Container_Resolver {\n\n constructor() {\n // VARS\n const _regNs = {};\n let _namespaces = [];\n let _ps = '/'; // web & unix path separator\n\n // INSTANCE METHODS\n\n this.addNamespaceRoot = function (ns, path, ext) {\n _regNs[ns] = {\n [KEY_EXT]: ext ?? _Defs_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].EXT,\n [KEY_NS]: ns,\n [KEY_PATH]: path,\n };\n _namespaces = Object.keys(_regNs).sort((a, b) => b.localeCompare(a));\n };\n\n /**\n * Convert the module name to the path of the source files .\n * @param {string} moduleName 'Vendor_Package_Module'\n * @return {string} '/home/user/app/node_modules/@vendor/package/src/Module.js'\n */\n this.resolve = function (moduleName) {\n let root, ext, ns;\n for (ns of _namespaces) {\n if (moduleName.startsWith(ns)) {\n root = _regNs[ns][KEY_PATH];\n ext = _regNs[ns][KEY_EXT];\n break;\n }\n }\n if (root && ext) {\n let tail = moduleName.replace(ns, '');\n if (tail.indexOf(NSS) === 0) tail = tail.replace(NSS, '');\n const file = tail.replaceAll(NSS, _ps);\n return `${root}${_ps}${file}.${ext}`;\n } else return moduleName;\n };\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Container/Resolver.js?");
118
118
 
119
119
  /***/ }),
120
120
 
121
- /***/ "./src/Resolver.js":
122
- /*!*************************!*\
123
- !*** ./src/Resolver.js ***!
124
- \*************************/
121
+ /***/ "./src/Defs.js":
122
+ /*!*********************!*\
123
+ !*** ./src/Defs.js ***!
124
+ \*********************/
125
125
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
126
126
 
127
127
  "use strict";
128
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_Resolver)\n/* harmony export */ });\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Defs.js */ \"./src/Defs.js\");\n/**\n * The Resolver should convert ES6 module name into the path to the sources (file path or URL).\n *\n * This is a base resolver that considers that:\n * - module name is Zend1-compatible ('Vendor_Package_Module')\n * - every namespace is bound to some real path ('Vendor_Package_' => '.../node_modules/@vendor/package/src/...)\n * - every package has sources with the same extensions (*.js, *.mjs, *.es6, ...)\n * - namespaces can be nested (App_Web_ => ./@app/web/..., App_Web_Api_ => ./@app/web_api/...)\n */\n\n\n// VARS\nconst KEY_EXT = 'ext';\nconst KEY_NS = 'ns';\nconst KEY_PATH = 'root';\n/**\n * Namespace parts separator.\n *\n * @type {string}\n */\nconst NSS = '_';\n\n// MAIN\nclass TeqFw_Di_Resolver {\n\n constructor() {\n // VARS\n const _regNs = {};\n let _namespaces = [];\n let _ps = '/'; // web & unix path separator\n\n // INSTANCE METHODS\n\n this.addNamespaceRoot = function (ns, path, ext) {\n _regNs[ns] = {\n [KEY_EXT]: ext ?? _Defs_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].EXT,\n [KEY_NS]: ns,\n [KEY_PATH]: path,\n };\n _namespaces = Object.keys(_regNs).sort((a, b) => b.localeCompare(a));\n };\n\n /**\n * Convert the module name to the path of the source files .\n * @param {string} moduleName 'Vendor_Package_Module'\n * @return {string} '/home/user/app/node_modules/@vendor/package/src/Module.js'\n */\n this.resolve = function (moduleName) {\n let root, ext, ns;\n for (ns of _namespaces) {\n if (moduleName.startsWith(ns)) {\n root = _regNs[ns][KEY_PATH];\n ext = _regNs[ns][KEY_EXT];\n break;\n }\n }\n if (root && ext) {\n const tail = moduleName.replace(ns, '');\n const file = tail.replaceAll(NSS, _ps);\n return `${root}${_ps}${file}.${ext}`;\n } else return moduleName;\n };\n }\n};\n\n//# sourceURL=webpack://@teqfw/di/./src/Resolver.js?");
128
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/**\n * Hardcoded constants and useful utilities for the package.\n * @namespace TeqFw_Di_Defs\n */\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n COMPOSE_AS_IS: 'A',\n COMPOSE_FACTORY: 'F',\n EXT: 'js',\n KEY_CONTAINER: 'container',\n KEY_CONTAINER_NS: 'TeqFw_Di_Container$',\n LIFE_INSTANCE: 'I',\n LIFE_SINGLETON: 'S',\n /**\n * @deprecated use TeqFw_Core_Shared_Defaults.DI_WRAP_PROXY\n */\n WRAP_PROXY: 'proxy',\n\n /**\n * Return 'true' if function is a class definition.\n * See: https://stackoverflow.com/a/29094018/4073821\n *\n * @param {function} fn\n * @return {boolean}\n */\n isClass(fn) {\n const proto = Object.getOwnPropertyDescriptor(fn, 'prototype');\n return proto && !proto.writable;\n },\n});\n\n//# sourceURL=webpack://@teqfw/di/./src/Defs.js?");
129
129
 
130
130
  /***/ }),
131
131
 
132
- /***/ "./src/SpecAnalyser.js":
133
- /*!*****************************!*\
134
- !*** ./src/SpecAnalyser.js ***!
135
- \*****************************/
132
+ /***/ "./src/DepId.js":
133
+ /*!**********************!*\
134
+ !*** ./src/DepId.js ***!
135
+ \**********************/
136
136
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
137
137
 
138
138
  "use strict";
139
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _Defs_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Defs.js */ \"./src/Defs.js\");\n/**\n * This function analyzes specification of dependencies extracted from the text definition of the function itself.\n */\n\n\n// VARS\nconst FUNC = /function\\s*\\w*\\s*\\((\\s*\\{.+\\}\\s*)\\)/s;\nconst CLASS = /constructor\\s*\\((\\s*\\{.+\\}\\s*)\\)/s;\n\n// FUNCS\n\n/**\n * Internal function to analyze extracted parameters.\n *\n * @param {string} params\n * @return {string[]}\n * @private\n */\nfunction _analyze(params) {\n const res = [];\n // create wrapper for arguments and collect dependencies using Proxy\n try {\n const fn = new Function(params, 'return');\n const spec = new Proxy({}, {\n get: (target, prop) => res.push(prop),\n });\n // run wrapper and return dependencies\n fn(spec);\n } catch (e) {\n const msg = `Cannot analyze the deps specification:${parts[1]}\\n`\n + `\\nPlease, be sure that spec does not contain extra ')' in a comments.`\n + `\\n\\nError: ${e}`;\n throw new Error(msg);\n }\n return res;\n}\n\n/**\n * @param {Function|Object} exp\n * @return {string[]}\n */\nfunction _analyzeClass(exp) {\n const res = [];\n // extract arguments from constructor\n const def = exp.toString();\n const parts = CLASS.exec(def);\n if (parts) {\n res.push(..._analyze(parts[1]));\n } // else: constructor does not have arguments\n return res;\n}\n\n/**\n * @param {Function|Object} exp\n * @return {string[]}\n */\nfunction _analyzeFunc(exp) {\n const res = [];\n // extract arguments from factory function\n const def = exp.toString();\n const parts = FUNC.exec(def);\n if (parts) {\n res.push(..._analyze(parts[1]));\n } // else: constructor does not have arguments\n return res;\n}\n\n// MAIN\n/**\n * @param {Function|Object} exp\n * @return {string[]}\n */\n/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(exp) {\n if (typeof exp === 'function') {\n if (_Defs_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].isClass(exp)) {\n return _analyzeClass(exp);\n } else {\n return _analyzeFunc(exp);\n }\n } else\n return [];\n}\n\n//# sourceURL=webpack://@teqfw/di/./src/SpecAnalyser.js?");
139
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TeqFw_Di_DepId)\n/* harmony export */ });\n/**\n * This is a DTO that represents the structure of an ID for a runtime dependency.\n * @namespace TeqFw_Di_DepId\n */\nclass TeqFw_Di_DepId {\n /**\n * The name of an export of the module.\n * @type {string}\n */\n exportName;\n /**\n * Composition type (see Defs.COMPOSE_): use the export as Factory (F) or return as-is (A).\n * @type {string}\n */\n composition;\n /**\n * Lifestyle type (see Defs.LIFE_): singleton (S) or instance (I).\n * @type {string}\n */\n life;\n /**\n * The code for ES6 module that can be converted to the path to this es6 module.\n * @type {string}\n */\n moduleName;\n /**\n * Object key value.\n * @type {string}\n */\n value;\n /**\n * List of wrappers to decorate the result.\n * @type {string[]}\n */\n wrappers = [];\n}\n\n//# sourceURL=webpack://@teqfw/di/./src/DepId.js?");
140
140
 
141
141
  /***/ })
142
142
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@teqfw/di",
3
- "version": "0.20.0",
4
- "description": "Dependency Injection container based on logical namespaces for ES6 modules.",
3
+ "version": "0.21.0",
4
+ "description": "Dependency Injection container for ES6 modules that works in both browser and Node.js apps.",
5
5
  "keywords": [
6
6
  "dependency injection",
7
7
  "di",
@@ -27,12 +27,20 @@
27
27
  "url": "git+https://github.com/teqfw/di.git"
28
28
  },
29
29
  "scripts": {
30
- "build": "rm -fr ./dist/ && webpack build"
30
+ "build": "rm -fr ./dist/ && webpack build",
31
+ "test": "mocha --recursive './test/**/*.test.mjs'"
31
32
  },
32
33
  "devDependencies": {
33
- "esm": "*",
34
- "mocha": "*",
35
- "webpack": "^5.88.1",
36
- "webpack-cli": "^5.1.4"
34
+ "babel-eslint": "latest",
35
+ "eslint": "latest",
36
+ "esm": "latest",
37
+ "mocha": "latest",
38
+ "webpack": "latest",
39
+ "webpack-cli": "latest"
40
+ },
41
+ "mocha":{
42
+ "require": "esm",
43
+ "spec": "./test/**/*.test.mjs",
44
+ "timeout": 5000
37
45
  }
38
46
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Interface for one chunk of the runtime dependency ID parser.
3
+ *
4
+ * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
+ * @interface
6
+ */
7
+ export default class TeqFw_Di_Api_Container_Parser_Chunk {
8
+
9
+ /**
10
+ * Returns 'true' if this chunk can parse the given dependency ID.
11
+ *
12
+ * @param {string} depId
13
+ * @return {boolean}
14
+ */
15
+ canParse(depId) {};
16
+
17
+ /**
18
+ * Parses a string ID for a runtime dependency and returns structured data (DTO).
19
+ * @param {string} depId
20
+ * @return {TeqFw_Di_DepId}
21
+ */
22
+ parse(depId) {}
23
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Interface for the parser of the runtime dependency ID.
3
+ *
4
+ * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
+ * @interface
6
+ */
7
+ export default class TeqFw_Di_Api_Container_Parser {
8
+ /**
9
+ * Adds the given chunk to the parser.
10
+ *
11
+ * @param {TeqFw_Di_Api_Container_Parser_Chunk} chunk
12
+ */
13
+ addChunk(chunk) {}
14
+
15
+ /**
16
+ * Parse given dependency ID and return structured data as DTO.
17
+ * @param {string} depId
18
+ * @return {TeqFw_Di_DepId}
19
+ */
20
+ parse(depId) {}
21
+
22
+ /**
23
+ * Sets the default chunk of the parser.
24
+ *
25
+ * @param {TeqFw_Di_Api_Container_Parser_Chunk} chunk
26
+ */
27
+ setDefaultChunk(chunk) {}
28
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interface for one chunk of the post-processor that modifies result.
3
+ *
4
+ * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
+ * @interface
6
+ */
7
+ export default class TeqFw_Di_Api_Container_PostProcessor_Chunk {
8
+
9
+ /**
10
+ * Modify result before returning to the caller.
11
+ * @param {*} obj - created object
12
+ * @param {TeqFw_Di_DepId} originalId - original `depId` DTO
13
+ * @param {string[]} stack - stack of parents depIds
14
+ * @return {*} modified object
15
+ */
16
+ modify(obj, originalId, stack) {}
17
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Interface for the post-processor of the result object.
3
+ *
4
+ * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
+ * @interface
6
+ */
7
+ export default class TeqFw_Di_Api_Container_PostProcessor {
8
+ /**
9
+ * Adds the given chunk to the parser.
10
+ *
11
+ * @param {TeqFw_Di_Api_Container_PostProcessor_Chunk} chunk
12
+ */
13
+ addChunk(chunk) {}
14
+
15
+ /**
16
+ * Modifies the result of the object composition.
17
+ *
18
+ * @param {*} obj - The result object to be modified.
19
+ * @param {TeqFw_Di_DepId} depId - The original depID DTO.
20
+ * @param {string[]} - The stack of parent IDs.
21
+ * @return {Promise<*>}
22
+ */
23
+ modify(obj, depId, stack) {}
24
+
25
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interface for one chunk of the pre-processor that modify initial `depId`.
3
+ *
4
+ * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
+ * @interface
6
+ */
7
+ export default class TeqFw_Di_Api_Container_PreProcessor_Chunk {
8
+
9
+ /**
10
+ * Modify runtime dependency ID before creating any object.
11
+ * @param {TeqFw_Di_DepId} depId - `depId` DTO after all previous pre-processing steps
12
+ * @param {TeqFw_Di_DepId} originalId - original `depId` DTO
13
+ * @param {string[]} stack - stack of parents depIds
14
+ * @return {TeqFw_Di_DepId}
15
+ */
16
+ modify(depId, originalId, stack) {}
17
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Interface for the pre-processor of the runtime dependency ID.
3
+ *
4
+ * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
+ * @interface
6
+ */
7
+ export default class TeqFw_Di_Api_Container_PreProcessor {
8
+ /**
9
+ * Adds the given chunk to the parser.
10
+ *
11
+ * @param {TeqFw_Di_Api_Container_PreProcessor_Chunk} chunk
12
+ */
13
+ addChunk(chunk) {}
14
+
15
+ /**
16
+ * Modify parsed depID and return it.
17
+ * @param {TeqFw_Di_DepId} depId - The depID as DTO.
18
+ * @param {string[]} stack - The stack of parent IDs.
19
+ * @return {TeqFw_Di_DepId} -
20
+ */
21
+ modify(depId, stack) {}
22
+
23
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Interface for the Object Container.
3
+ *
4
+ * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
+ * @interface
6
+ */
7
+ export default class TeqFw_Di_Api_Container {
8
+ /**
9
+ * Gets or creates a runtime object by ID.
10
+ *
11
+ * @param {string} runtimeDepId - The ID of the runtime object.
12
+ * @return {Promise<*>} - A promise that resolves to the runtime object.
13
+ */
14
+ get(runtimeDepId) {};
15
+
16
+ /**
17
+ * @return {TeqFw_Di_Api_Container_Parser}
18
+ */
19
+ getParser() {};
20
+
21
+ /**
22
+ * @return {TeqFw_Di_Api_Container_PreProcessor}
23
+ */
24
+ getPreProcessor() {};
25
+
26
+ /**
27
+ * @return {TeqFw_Di_Api_Container_PostProcessor}
28
+ */
29
+ getPostProcessor() {};
30
+
31
+ /**
32
+ * @return {TeqFw_Di_Container_Resolver}
33
+ */
34
+ getResolver() {};
35
+
36
+ /**
37
+ * Enable disable debug output for the object composition process.
38
+ * @param {boolean} data
39
+ */
40
+ setDebug(data) {};
41
+
42
+ /**
43
+ * @param {TeqFw_Di_Api_Container_Parser} data
44
+ */
45
+ setParser(data) {};
46
+
47
+ /**
48
+ * @param {TeqFw_Di_Api_Container_PreProcessor} data
49
+ */
50
+ setPreProcessor(data) {};
51
+
52
+ /**
53
+ * @param {TeqFw_Di_Api_Container_PostProcessor} data
54
+ */
55
+ setPostProcessor(data) {};
56
+
57
+ /**
58
+ * @param {TeqFw_Di_Container_Resolver} data
59
+ */
60
+ setResolver(data) {};
61
+ };
@@ -1,11 +1,15 @@
1
1
  /**
2
- * This function analyzes specification of dependencies extracted from the text definition of the function itself.
2
+ * This function analyses specification of dependencies extracted from the text definition of the function itself.
3
+ *
4
+ * This is a local module and is used only inside the `TeqFw_Di_Container_A_Composer` space.
5
+ *
6
+ * @namespace TeqFw_Di_Container_A_Composer_A_SpecParser
3
7
  */
4
- import Defs from './Defs.js';
8
+ import Defs from '../../../../Defs.js';
5
9
 
6
10
  // VARS
7
- const FUNC = /function\s*\w*\s*\((\s*\{.+\}\s*)\)/s;
8
- const CLASS = /constructor\s*\((\s*\{.+\}\s*)\)/s;
11
+ const FUNC = /(function)*\s*\w*\s*\(\s*\{([^\}]*)\}/s;
12
+ const CLASS = /constructor\s*\(\s*\{([^\}]*)\}/s;
9
13
 
10
14
  // FUNCS
11
15
 
@@ -20,14 +24,14 @@ function _analyze(params) {
20
24
  const res = [];
21
25
  // create wrapper for arguments and collect dependencies using Proxy
22
26
  try {
23
- const fn = new Function(params, 'return');
27
+ const fn = new Function(`{${params}}`, 'return');
24
28
  const spec = new Proxy({}, {
25
29
  get: (target, prop) => res.push(prop),
26
30
  });
27
31
  // run wrapper and return dependencies
28
32
  fn(spec);
29
33
  } catch (e) {
30
- const msg = `Cannot analyze the deps specification:${parts[1]}\n`
34
+ const msg = `Cannot analyze the deps specification:${params}\n`
31
35
  + `\nPlease, be sure that spec does not contain extra ')' in a comments.`
32
36
  + `\n\nError: ${e}`;
33
37
  throw new Error(msg);
@@ -60,7 +64,7 @@ function _analyzeFunc(exp) {
60
64
  const def = exp.toString();
61
65
  const parts = FUNC.exec(def);
62
66
  if (parts) {
63
- res.push(..._analyze(parts[1]));
67
+ res.push(..._analyze(parts[2]));
64
68
  } // else: constructor does not have arguments
65
69
  return res;
66
70
  }