@teqfw/di 0.33.0 → 0.34.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/RELEASE.md +11 -0
- package/dist/esm.js +1 -1
- package/dist/umd.js +1 -1
- package/package.json +1 -1
- package/src/Container/A/Composer.js +2 -2
- package/src/Container.js +39 -36
- package/src/Api/Container.js +0 -69
package/RELEASE.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @teqfw/di releases
|
|
2
2
|
|
|
3
|
+
## 0.34.0 – Strict Mode and Test Support
|
|
4
|
+
|
|
5
|
+
- Removed outdated interface `TeqFw_Di_Api_Container` and associated documentation.
|
|
6
|
+
- Unified the `get()` and `compose()` methods for dependency retrieval.
|
|
7
|
+
- Introduced strict mode by default: manual registration of dependencies is now **disabled** unless explicitly allowed.
|
|
8
|
+
- Added `enableTestMode()` method to the container, enabling safe, test-specific manual registration of singleton
|
|
9
|
+
dependencies.
|
|
10
|
+
- Improved error messages and safeguards against accidental overwrites in `register()`.
|
|
11
|
+
- Updated internal naming and documentation for better clarity and alignment with the platform's principles.
|
|
12
|
+
- Cleaned up ESLint and JSDoc inconsistencies in internal files.
|
|
13
|
+
|
|
3
14
|
## 0.33.0 – Cleanup and Enhancements
|
|
4
15
|
|
|
5
16
|
- Removed deprecated documentation.
|
package/dist/esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e={CA:"A",CF:"F",ID:"container",ID_FQN:"TeqFw_Di_Container$",LI:"I",LS:"S",isClass(e){const t=Object.getOwnPropertyDescriptor(e,"prototype");return t&&!t.writable}};const t=/(function)*\s*\w*\s*\(\s*\{([^}]*)}/s,o=/constructor\s*\(\s*\{([^}]*)}/s;function n(e){const t=[];try{const o=new Function(`{${e}}`,"return");o(new Proxy({},{get:(e,o)=>t.push(o)}))}catch(t){throw new Error(`Cannot analyze the deps specification:${e}\n\nPlease, be sure that spec does not contain extra ')' in a comments.\n\nError: ${t}`)}return t}function s(s){return"function"==typeof s?e.isClass(s)?function(e){const t=[],s=e.toString(),r=o.exec(s);return r&&t.push(...n(r[1])),t}(s):function(e){const o=[],s=e.toString(),r=t.exec(s);return r&&o.push(...n(r[2])),o}(s):[]}class r{constructor(){let t=!1;this.create=async function(o,n,r,i){if(r.includes(o.origin))throw new Error(`Circular dependency for '${o.origin}'. Parents are: ${JSON.stringify(r)}`);if(o.exportName){const a=[...r,o.origin],{[o.exportName]:
|
|
1
|
+
var e={CA:"A",CF:"F",ID:"container",ID_FQN:"TeqFw_Di_Container$",LI:"I",LS:"S",isClass(e){const t=Object.getOwnPropertyDescriptor(e,"prototype");return t&&!t.writable}};const t=/(function)*\s*\w*\s*\(\s*\{([^}]*)}/s,o=/constructor\s*\(\s*\{([^}]*)}/s;function n(e){const t=[];try{const o=new Function(`{${e}}`,"return");o(new Proxy({},{get:(e,o)=>t.push(o)}))}catch(t){throw new Error(`Cannot analyze the deps specification:${e}\n\nPlease, be sure that spec does not contain extra ')' in a comments.\n\nError: ${t}`)}return t}function s(s){return"function"==typeof s?e.isClass(s)?function(e){const t=[],s=e.toString(),r=o.exec(s);return r&&t.push(...n(r[1])),t}(s):function(e){const o=[],s=e.toString(),r=t.exec(s);return r&&o.push(...n(r[2])),o}(s):[]}class r{constructor(){let t=!1;this.create=async function(o,n,r,i){if(r.includes(o.origin))throw new Error(`Circular dependency for '${o.origin}'. Parents are: ${JSON.stringify(r)}`);if(o.exportName){const a=[...r,o.origin],{[o.exportName]:l}=n;if(o.composition===e.CF){if("function"==typeof l){const n=s(l);n.length&&(c=`Deps for object '${o.origin}' are: ${JSON.stringify(n)}`,t&&console.log(c));const r={};for(const e of n)r[e]=await i.get(e,a);const u=e.isClass(l)?new l(r):l(r);return u instanceof Promise?await u:u}return Object.assign({},l)}return l}return n;var c},this.setDebug=function(e){t=e}}}class i{exportName;composition;life;moduleName;origin;wrappers=[]}const c=/^(node:)?(@?[A-Za-z0-9_-]+\/?[A-Za-z0-9_-]*)(([.#])?([A-Za-z0-9_]*)((\$)?(\$)?)?)?(\(([A-Za-z0-9_,]*)\))?$/;class a{canParse(){return!0}parse(t){const o=new i;o.origin=t;const n=c.exec(t);if(n&&(o.isNodeModule=Boolean(n[1]),o.moduleName=n[2].replace(/^node:/,""),"."===n[4]||"#"===n[4]?"$"===n[6]||"$$"===n[6]?(o.composition=e.CF,o.exportName=n[5],o.life="$"===n[6]?e.LS:e.LI):(o.composition=e.CA,o.life=e.LS,o.exportName=""!==n[5]?n[5]:"default"):"$"===n[6]||"$$"===n[6]?(o.composition=e.CF,o.exportName="default",o.life="$"===n[6]?e.LS:e.LI):(o.composition=void 0,o.exportName=void 0,o.life=void 0),n[10]&&(o.wrappers=n[10].split(","))),o.composition===e.CA&&o.life===e.LI)throw new Error(`Export is not a function and should be used as a singleton only: '${o.origin}'.`);return o}}class l{constructor(){let e=new a;const t=[];this.addChunk=function(e){t.push(e)},this.parse=function(o){let n;for(const e of t)if(e.canParse(o)){n=e.parse(o);break}return n||(n=e?.parse(o)),n},this.setDefaultChunk=function(t){e=t}}}class u{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=function(t,o){let n=t;for(const s of e)n=s.modify(n,t,o);return n}}}class f{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=async function(t,o,n){let s=t;for(const t of e)s=t.modify(s,o,n),s instanceof Promise&&(s=await s);return s}}}const d="ext",p="ns",h="root";class m{constructor(){const e={};let t=!1,o=[],n="/";this.addNamespaceRoot=function(n,s,r){const i=(t?s.replace(/^\\/,""):s).replace(/\\/g,"/"),c=t?`file://${i}`:i;e[n]={[d]:r??"js",[p]:n,[h]:c},o=Object.keys(e).sort(((e,t)=>t.localeCompare(e)))},this.resolve=function(t){let s,r,i;for(i of o)if(t.startsWith(i)){s=e[i][h],r=e[i].ext;break}if(s&&r){let e=t.replace(i,"");0===e.indexOf("_")&&(e=e.replace("_",""));const o=e.replaceAll("_",n);return`${s}${n}${o}.${r}`}return t},this.setWindowsEnv=function(e=!0){t=e,n=e?"\\":"/"}}}function $(e){return`${e.moduleName}#${e.exportName}`}class g{constructor(){let t=new r,o=!1,n=new l,s=new f,i=new u,c=!1;const a={},d={};let p=new m;function h(){o&&console.log(...arguments)}this.get=async function(o,r=[]){if(h(`Object '${o}' is requested.`),o===e.ID||o===e.ID_FQN)return h("Container itself is returned."),d[e.ID];const c=n.parse(o),l=i.modify(c,r);if(l.life===e.LS){const e=$(l);if(d[e])return h(`Existing singleton '${e}' is returned.`),d[e]}let u;a[l.moduleName]||(h(`ES6 module '${l.moduleName}' is not resolved yet`),a[l.moduleName]=p.resolve(l.moduleName));const f=a[l.moduleName];try{u=await import(f),h(`ES6 module '${l.moduleName}' is loaded from '${f}'.`)}catch(e){throw console.error(e?.message,`Object key: "${o}".`,`Path: "${f}".`,`Stack: ${JSON.stringify(r)}`),e}let m=await t.create(l,u,r,this);var g;if(null===(g=m)||"object"!=typeof g&&"function"!=typeof g||"[object Module]"===Object.prototype.toString.call(g)||Object.isFrozen(g)||Object.freeze(m),m=await s.modify(m,l,r),h(`Object '${o}' is created.`),l.life===e.LS){const e=$(l);d[e]=m,h(`Object '${o}' is saved as singleton.`)}return m},this.enableTestMode=function(){c=!0,h("Test mode enabled")},this.getParser=()=>n,this.getPreProcessor=()=>i,this.getPostProcessor=()=>s,this.getResolver=()=>p,this.register=function(t,o){if(!c)throw new Error("Use enableTestMode() to allow it");if(!t||!o)throw new Error("Both params are required");const s=n.parse(t);if(s.life!==e.LS)throw new Error(`Only singletons can be registered: '${t}'`);const r=$(s);if(d[r])throw new Error(`'${t}' is already registered`);d[r]=o,h(`'${t}' is registered`)},this.setDebug=function(e){o=e,t.setDebug(e)},this.setParser=e=>n=e,this.setPreProcessor=e=>i=e,this.setPostProcessor=e=>s=e,this.setResolver=e=>p=e,d[e.ID]=this}}export{g as default};
|
package/dist/umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TeqFw_Di_Container=t()}(this,(function(){"use strict";var e={CA:"A",CF:"F",ID:"container",ID_FQN:"TeqFw_Di_Container$",LI:"I",LS:"S",isClass(e){const t=Object.getOwnPropertyDescriptor(e,"prototype");return t&&!t.writable}};const t=/(function)*\s*\w*\s*\(\s*\{([^}]*)}/s,o=/constructor\s*\(\s*\{([^}]*)}/s;function n(e){const t=[];try{const o=new Function(`{${e}}`,"return");o(new Proxy({},{get:(e,o)=>t.push(o)}))}catch(t){throw new Error(`Cannot analyze the deps specification:${e}\n\nPlease, be sure that spec does not contain extra ')' in a comments.\n\nError: ${t}`)}return t}function s(s){return"function"==typeof s?e.isClass(s)?function(e){const t=[],s=e.toString(),r=o.exec(s);return r&&t.push(...n(r[1])),t}(s):function(e){const o=[],s=e.toString(),r=t.exec(s);return r&&o.push(...n(r[2])),o}(s):[]}class r{constructor(){let t=!1;this.create=async function(o,n,r,i){if(r.includes(o.origin))throw new Error(`Circular dependency for '${o.origin}'. Parents are: ${JSON.stringify(r)}`);if(o.exportName){const a=[...r,o.origin],{[o.exportName]:u}=n;if(o.composition===e.CF){if("function"==typeof u){const n=s(u);n.length&&(c=`Deps for object '${o.origin}' are: ${JSON.stringify(n)}`,t&&console.log(c));const r={};for(const e of n)r[e]=await i.
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TeqFw_Di_Container=t()}(this,(function(){"use strict";var e={CA:"A",CF:"F",ID:"container",ID_FQN:"TeqFw_Di_Container$",LI:"I",LS:"S",isClass(e){const t=Object.getOwnPropertyDescriptor(e,"prototype");return t&&!t.writable}};const t=/(function)*\s*\w*\s*\(\s*\{([^}]*)}/s,o=/constructor\s*\(\s*\{([^}]*)}/s;function n(e){const t=[];try{const o=new Function(`{${e}}`,"return");o(new Proxy({},{get:(e,o)=>t.push(o)}))}catch(t){throw new Error(`Cannot analyze the deps specification:${e}\n\nPlease, be sure that spec does not contain extra ')' in a comments.\n\nError: ${t}`)}return t}function s(s){return"function"==typeof s?e.isClass(s)?function(e){const t=[],s=e.toString(),r=o.exec(s);return r&&t.push(...n(r[1])),t}(s):function(e){const o=[],s=e.toString(),r=t.exec(s);return r&&o.push(...n(r[2])),o}(s):[]}class r{constructor(){let t=!1;this.create=async function(o,n,r,i){if(r.includes(o.origin))throw new Error(`Circular dependency for '${o.origin}'. Parents are: ${JSON.stringify(r)}`);if(o.exportName){const a=[...r,o.origin],{[o.exportName]:u}=n;if(o.composition===e.CF){if("function"==typeof u){const n=s(u);n.length&&(c=`Deps for object '${o.origin}' are: ${JSON.stringify(n)}`,t&&console.log(c));const r={};for(const e of n)r[e]=await i.get(e,a);const l=e.isClass(u)?new u(r):u(r);return l instanceof Promise?await l:l}return Object.assign({},u)}return u}return n;var c},this.setDebug=function(e){t=e}}}class i{exportName;composition;life;moduleName;origin;wrappers=[]}const c=/^(node:)?(@?[A-Za-z0-9_-]+\/?[A-Za-z0-9_-]*)(([.#])?([A-Za-z0-9_]*)((\$)?(\$)?)?)?(\(([A-Za-z0-9_,]*)\))?$/;class a{canParse(){return!0}parse(t){const o=new i;o.origin=t;const n=c.exec(t);if(n&&(o.isNodeModule=Boolean(n[1]),o.moduleName=n[2].replace(/^node:/,""),"."===n[4]||"#"===n[4]?"$"===n[6]||"$$"===n[6]?(o.composition=e.CF,o.exportName=n[5],o.life="$"===n[6]?e.LS:e.LI):(o.composition=e.CA,o.life=e.LS,o.exportName=""!==n[5]?n[5]:"default"):"$"===n[6]||"$$"===n[6]?(o.composition=e.CF,o.exportName="default",o.life="$"===n[6]?e.LS:e.LI):(o.composition=void 0,o.exportName=void 0,o.life=void 0),n[10]&&(o.wrappers=n[10].split(","))),o.composition===e.CA&&o.life===e.LI)throw new Error(`Export is not a function and should be used as a singleton only: '${o.origin}'.`);return o}}class u{constructor(){let e=new a;const t=[];this.addChunk=function(e){t.push(e)},this.parse=function(o){let n;for(const e of t)if(e.canParse(o)){n=e.parse(o);break}return n||(n=e?.parse(o)),n},this.setDefaultChunk=function(t){e=t}}}class l{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=function(t,o){let n=t;for(const s of e)n=s.modify(n,t,o);return n}}}class f{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=async function(t,o,n){let s=t;for(const t of e)s=t.modify(s,o,n),s instanceof Promise&&(s=await s);return s}}}const d="ext",p="ns",h="root";class m{constructor(){const e={};let t=!1,o=[],n="/";this.addNamespaceRoot=function(n,s,r){const i=(t?s.replace(/^\\/,""):s).replace(/\\/g,"/"),c=t?`file://${i}`:i;e[n]={[d]:r??"js",[p]:n,[h]:c},o=Object.keys(e).sort(((e,t)=>t.localeCompare(e)))},this.resolve=function(t){let s,r,i;for(i of o)if(t.startsWith(i)){s=e[i][h],r=e[i].ext;break}if(s&&r){let e=t.replace(i,"");0===e.indexOf("_")&&(e=e.replace("_",""));const o=e.replaceAll("_",n);return`${s}${n}${o}.${r}`}return t},this.setWindowsEnv=function(e=!0){t=e,n=e?"\\":"/"}}}function g(e){return`${e.moduleName}#${e.exportName}`}return class{constructor(){let t=new r,o=!1,n=new u,s=new f,i=new l,c=!1;const a={},d={};let p=new m;function h(){o&&console.log(...arguments)}this.get=async function(o,r=[]){if(h(`Object '${o}' is requested.`),o===e.ID||o===e.ID_FQN)return h("Container itself is returned."),d[e.ID];const c=n.parse(o),u=i.modify(c,r);if(u.life===e.LS){const e=g(u);if(d[e])return h(`Existing singleton '${e}' is returned.`),d[e]}let l;a[u.moduleName]||(h(`ES6 module '${u.moduleName}' is not resolved yet`),a[u.moduleName]=p.resolve(u.moduleName));const f=a[u.moduleName];try{l=await import(f),h(`ES6 module '${u.moduleName}' is loaded from '${f}'.`)}catch(e){throw console.error(e?.message,`Object key: "${o}".`,`Path: "${f}".`,`Stack: ${JSON.stringify(r)}`),e}let m=await t.create(u,l,r,this);var w;if(null===(w=m)||"object"!=typeof w&&"function"!=typeof w||"[object Module]"===Object.prototype.toString.call(w)||Object.isFrozen(w)||Object.freeze(m),m=await s.modify(m,u,r),h(`Object '${o}' is created.`),u.life===e.LS){const e=g(u);d[e]=m,h(`Object '${o}' is saved as singleton.`)}return m},this.enableTestMode=function(){c=!0,h("Test mode enabled")},this.getParser=()=>n,this.getPreProcessor=()=>i,this.getPostProcessor=()=>s,this.getResolver=()=>p,this.register=function(t,o){if(!c)throw new Error("Use enableTestMode() to allow it");if(!t||!o)throw new Error("Both params are required");const s=n.parse(t);if(s.life!==e.LS)throw new Error(`Only singletons can be registered: '${t}'`);const r=g(s);if(d[r])throw new Error(`'${t}' is already registered`);d[r]=o,h(`'${t}' is registered`)},this.setDebug=function(e){o=e,t.setDebug(e)},this.setParser=e=>n=e,this.setPreProcessor=e=>i=e,this.setPostProcessor=e=>s=e,this.setResolver=e=>p=e,d[e.ID]=this}}}));
|
package/package.json
CHANGED
|
@@ -23,7 +23,7 @@ export default class TeqFw_Di_Container_A_Composer {
|
|
|
23
23
|
* Returns or creates and returns the requested object.
|
|
24
24
|
*
|
|
25
25
|
* @param {TeqFw_Di_DepId} depId
|
|
26
|
-
* @param {
|
|
26
|
+
* @param {object} module - imported es6 module
|
|
27
27
|
* @param {string[]} stack - array of the parent objects IDs to prevent dependency loop
|
|
28
28
|
* @param {TeqFw_Di_Container} container - to create dependencies for requested object
|
|
29
29
|
* @returns {Promise<*>}
|
|
@@ -42,7 +42,7 @@ export default class TeqFw_Di_Container_A_Composer {
|
|
|
42
42
|
if (deps.length) log(`Deps for object '${depId.origin}' are: ${JSON.stringify(deps)}`);
|
|
43
43
|
const spec = {};
|
|
44
44
|
for (const dep of deps)
|
|
45
|
-
spec[dep] = await container.
|
|
45
|
+
spec[dep] = await container.get(dep, stackNew);
|
|
46
46
|
// create a new object with the factory function
|
|
47
47
|
const res = (Defs.isClass(exp)) ? new exp(spec) : exp(spec);
|
|
48
48
|
if (res instanceof Promise)
|
package/src/Container.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The Object Container (composition root).
|
|
3
|
+
* We can use static imports in the Container.
|
|
4
|
+
*
|
|
3
5
|
* @namespace TeqFw_Di_Container
|
|
4
6
|
*/
|
|
5
7
|
import Composer from './Container/A/Composer.js';
|
|
@@ -33,11 +35,7 @@ function canBeFrozen(value) {
|
|
|
33
35
|
return !Object.isFrozen(value);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
|
|
37
38
|
// MAIN
|
|
38
|
-
/**
|
|
39
|
-
* @implements TeqFw_Di_Api_Container
|
|
40
|
-
*/
|
|
41
39
|
export default class TeqFw_Di_Container {
|
|
42
40
|
|
|
43
41
|
constructor() {
|
|
@@ -45,8 +43,9 @@ export default class TeqFw_Di_Container {
|
|
|
45
43
|
let _composer = new Composer();
|
|
46
44
|
let _debug = false;
|
|
47
45
|
let _parser = new Parser();
|
|
48
|
-
let _preProcessor = new PreProcessor();
|
|
49
46
|
let _postProcessor = new PostProcessor();
|
|
47
|
+
let _preProcessor = new PreProcessor();
|
|
48
|
+
let _testMode = false;
|
|
50
49
|
|
|
51
50
|
/**
|
|
52
51
|
* Registry for paths for loaded es6 modules.
|
|
@@ -56,7 +55,7 @@ export default class TeqFw_Di_Container {
|
|
|
56
55
|
const _regPaths = {};
|
|
57
56
|
/**
|
|
58
57
|
* Registry to store singletons.
|
|
59
|
-
* @type {Object<string,
|
|
58
|
+
* @type {Object<string, object>}
|
|
60
59
|
*/
|
|
61
60
|
const _regSingles = {};
|
|
62
61
|
let _resolver = new Resolver();
|
|
@@ -69,20 +68,9 @@ export default class TeqFw_Di_Container {
|
|
|
69
68
|
|
|
70
69
|
// INSTANCE METHODS
|
|
71
70
|
|
|
72
|
-
this.get = async function (
|
|
73
|
-
return this.compose(runtimeDepId, stack);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* This method is 'private' for the npm package. It is used in the Composer only.
|
|
78
|
-
*
|
|
79
|
-
* @param {string} depId runtime dependency ID
|
|
80
|
-
* @param {string[]} stack set of the depId to detect circular dependencies
|
|
81
|
-
* @returns {Promise<*>}
|
|
82
|
-
*/
|
|
83
|
-
this.compose = async function (depId, stack = []) {
|
|
71
|
+
this.get = async function (depId, stack = []) {
|
|
84
72
|
log(`Object '${depId}' is requested.`);
|
|
85
|
-
// return container itself if requested
|
|
73
|
+
// return the container itself if requested
|
|
86
74
|
if (
|
|
87
75
|
(depId === Defs.ID) ||
|
|
88
76
|
(depId === Defs.ID_FQN)
|
|
@@ -92,7 +80,7 @@ export default class TeqFw_Di_Container {
|
|
|
92
80
|
}
|
|
93
81
|
// parse the `objectKey` and get the structured DTO
|
|
94
82
|
const parsed = _parser.parse(depId);
|
|
95
|
-
// modify original key according to some rules (replacements, etc.)
|
|
83
|
+
// modify the original key according to some rules (replacements, etc.)
|
|
96
84
|
const key = _preProcessor.modify(parsed, stack);
|
|
97
85
|
// return existing singleton
|
|
98
86
|
if (key.life === Defs.LS) {
|
|
@@ -102,10 +90,10 @@ export default class TeqFw_Di_Container {
|
|
|
102
90
|
return _regSingles[singleId];
|
|
103
91
|
}
|
|
104
92
|
}
|
|
105
|
-
// resolve path to es6 module if not resolved before
|
|
93
|
+
// resolve a path to es6 module if not resolved before
|
|
106
94
|
if (!_regPaths[key.moduleName]) {
|
|
107
95
|
log(`ES6 module '${key.moduleName}' is not resolved yet`);
|
|
108
|
-
// convert module name to the path to es6-module file with a
|
|
96
|
+
// convert the module name to the path to an es6-module file with a source
|
|
109
97
|
_regPaths[key.moduleName] = _resolver.resolve(key.moduleName);
|
|
110
98
|
}
|
|
111
99
|
|
|
@@ -124,9 +112,9 @@ export default class TeqFw_Di_Container {
|
|
|
124
112
|
);
|
|
125
113
|
throw e;
|
|
126
114
|
}
|
|
127
|
-
// create object using the composer then modify it in post-processor
|
|
115
|
+
// create an object using the composer, then modify it in post-processor
|
|
128
116
|
let res = await _composer.create(key, module, stack, this);
|
|
129
|
-
// freeze the result to prevent modifications
|
|
117
|
+
// freeze the result to prevent modifications
|
|
130
118
|
if (canBeFrozen(res)) Object.freeze(res);
|
|
131
119
|
res = await _postProcessor.modify(res, key, stack);
|
|
132
120
|
log(`Object '${depId}' is created.`);
|
|
@@ -140,6 +128,14 @@ export default class TeqFw_Di_Container {
|
|
|
140
128
|
return res;
|
|
141
129
|
};
|
|
142
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Enables test mode, allowing manual singleton registration.
|
|
133
|
+
*/
|
|
134
|
+
this.enableTestMode = function () {
|
|
135
|
+
_testMode = true;
|
|
136
|
+
log('Test mode enabled');
|
|
137
|
+
};
|
|
138
|
+
|
|
143
139
|
this.getParser = () => _parser;
|
|
144
140
|
|
|
145
141
|
this.getPreProcessor = () => _preProcessor;
|
|
@@ -149,21 +145,28 @@ export default class TeqFw_Di_Container {
|
|
|
149
145
|
this.getResolver = () => _resolver;
|
|
150
146
|
|
|
151
147
|
/**
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* @param {
|
|
148
|
+
* Registers a new singleton object in the Container.
|
|
149
|
+
*
|
|
150
|
+
* @param {string} depId - Dependency identifier. Must be a singleton identifier.
|
|
151
|
+
* @param {object} obj - The object to register.
|
|
155
152
|
*/
|
|
156
153
|
this.register = function (depId, obj) {
|
|
157
|
-
if (!
|
|
154
|
+
if (!_testMode)
|
|
155
|
+
throw new Error('Use enableTestMode() to allow it');
|
|
156
|
+
|
|
157
|
+
if (!depId || !obj)
|
|
158
|
+
throw new Error('Both params are required');
|
|
159
|
+
|
|
158
160
|
const key = _parser.parse(depId);
|
|
159
|
-
if (key.life
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
161
|
+
if (key.life !== Defs.LS)
|
|
162
|
+
throw new Error(`Only singletons can be registered: '${depId}'`);
|
|
163
|
+
|
|
164
|
+
const singleId = getSingletonId(key);
|
|
165
|
+
if (_regSingles[singleId])
|
|
166
|
+
throw new Error(`'${depId}' is already registered`);
|
|
167
|
+
|
|
168
|
+
_regSingles[singleId] = obj;
|
|
169
|
+
log(`'${depId}' is registered`);
|
|
167
170
|
};
|
|
168
171
|
|
|
169
172
|
this.setDebug = function (data) {
|
package/src/Api/Container.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
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
|
-
* @param {string[]} [stack]
|
|
13
|
-
* @returns {Promise<*>} - A promise that resolves to the runtime object.
|
|
14
|
-
*/
|
|
15
|
-
get(runtimeDepId, stack) {};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @returns {TeqFw_Di_Api_Container_Parser}
|
|
19
|
-
*/
|
|
20
|
-
getParser() {};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @returns {TeqFw_Di_Api_Container_PreProcessor}
|
|
24
|
-
*/
|
|
25
|
-
getPreProcessor() {};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @returns {TeqFw_Di_Api_Container_PostProcessor}
|
|
29
|
-
*/
|
|
30
|
-
getPostProcessor() {};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @returns {TeqFw_Di_Container_Resolver} - the default resolver
|
|
34
|
-
*/
|
|
35
|
-
getResolver() {};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Registers an object (module, singleton, factory, or prototype) by dependency ID.
|
|
39
|
-
* @param {string} depId
|
|
40
|
-
* @param {Object} obj
|
|
41
|
-
*/
|
|
42
|
-
register(depId, obj) {};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Enable disable debug output for the object composition process.
|
|
46
|
-
* @param {boolean} data
|
|
47
|
-
*/
|
|
48
|
-
setDebug(data) {};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @param {TeqFw_Di_Api_Container_Parser} data
|
|
52
|
-
*/
|
|
53
|
-
setParser(data) {};
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @param {TeqFw_Di_Api_Container_PreProcessor} data
|
|
57
|
-
*/
|
|
58
|
-
setPreProcessor(data) {};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @param {TeqFw_Di_Api_Container_PostProcessor} data
|
|
62
|
-
*/
|
|
63
|
-
setPostProcessor(data) {};
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @param {TeqFw_Di_Api_Container_Resolver} data
|
|
67
|
-
*/
|
|
68
|
-
setResolver(data) {};
|
|
69
|
-
};
|