@teqfw/di 2.1.0 → 2.2.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/CHANGELOG.md +6 -0
- package/ai/container.md +2 -2
- package/ai/dependency-id.md +2 -2
- package/dist/esm.js +1 -1
- package/dist/umd.js +1 -1
- package/package.json +1 -1
- package/src/Container/Resolve/GraphResolver.mjs +2 -10
- package/src/Container.mjs +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.0 - 2026-03-16 - Agent interface alignment release
|
|
4
|
+
|
|
5
|
+
- Clarified lifecycle marker semantics in the agent interface documentation to match parser behavior (`$`, `$$`, and `$$$`).
|
|
6
|
+
- Updated container state model terminology in agent documentation to align with runtime state names.
|
|
7
|
+
- Updated package version metadata to `2.2.0`.
|
|
8
|
+
|
|
3
9
|
## 2.1.0 - 2026-03-16 - Protected proxy lifecycle handling
|
|
4
10
|
|
|
5
11
|
- Fixed container lifecycle handling for protected proxy components that reject `.then` probing or freezing.
|
package/ai/container.md
CHANGED
|
@@ -53,8 +53,8 @@ The exact semantics of dependency identifiers are defined in **dependency-id.md*
|
|
|
53
53
|
|
|
54
54
|
The container operates in three states:
|
|
55
55
|
|
|
56
|
-
- **
|
|
57
|
-
- **
|
|
56
|
+
- **notConfigured** — the container is being configured and dependencies may be registered.
|
|
57
|
+
- **operational** — the container resolves dependencies and produces linked objects.
|
|
58
58
|
- **failed** — the container has encountered an unrecoverable error.
|
|
59
59
|
|
|
60
60
|
If an error occurs during dependency resolution or any pipeline stage, the container transitions to the **failed** state. Once the container enters this state, all subsequent dependency requests are rejected.
|
package/ai/dependency-id.md
CHANGED
|
@@ -84,8 +84,8 @@ Lifecycle markers define how the container instantiates and returns objects.
|
|
|
84
84
|
The following markers are supported:
|
|
85
85
|
|
|
86
86
|
- **`$`** — singleton lifecycle; the container creates the object once and returns the same instance for subsequent requests.
|
|
87
|
-
- **`$$`** —
|
|
88
|
-
- **`$$$`** — transient lifecycle; the
|
|
87
|
+
- **`$$`** — transient lifecycle; a new instance is created for each request.
|
|
88
|
+
- **`$$$`** — transient lifecycle alias; behaves the same as `$$`.
|
|
89
89
|
|
|
90
90
|
Lifecycle markers are appended at the end of the identifier.
|
|
91
91
|
|
package/dist/esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.freeze({AS_IS:"A",FACTORY:"F"});var t=Object.freeze({SINGLETON:"S",TRANSIENT:"T"});var o=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const r=o.TEQ,n=e.AS_IS,i=new Set(Object.values(o)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let l=class{moduleName;platform;exportName;composition;life;wrappers;origin},c=class{create(e){const t=e&&"object"==typeof e?e:{},o=new l;o.moduleName="string"==typeof t.moduleName?t.moduleName:"";const c="string"==typeof t.platform?t.platform:void 0;o.platform=c&&i.has(c)?c:r;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),o.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;o.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return o.life=u&&a.has(u)?u:null,o.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],o.origin="string"==typeof t.origin?t.origin:"",Object.freeze(o.wrappers),Object.freeze(o)}};class p{constructor(){const r=new c;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("CDC must be a string.");if(0===i.length)throw new Error("CDC must be non-empty.");if(!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(i))throw new Error("CDC must satisfy AsciiCdcIdentifier.");const s=i;let a=i,l=o.TEQ;if(a.startsWith("node_"))l=o.NODE,a=a.slice(5);else if(a.startsWith("npm_"))l=o.NPM,a=a.slice(4);else if(a.startsWith("teq_"))throw new Error("Explicit teq_ prefix is forbidden.");if(0===a.length)throw new Error("moduleName must be non-empty.");const c=a.match(/(\${1,3})(?:_([A-Za-z0-9]+(?:_[A-Za-z0-9]+)*))?$/);let p=null,f=[],u=a;if(c){const e=c[1],o=c[2];if("$"===e)p=t.SINGLETON;else{if("$$"!==e&&"$$$"!==e)throw new Error("Lifecycle marker overflow.");p=t.TRANSIENT}if(u=a.slice(0,c.index),o){f=o.split("_");for(const e of f){if(!e)throw new Error("Wrapper must be non-empty.");if(e.includes("$"))throw new Error("Wrapper must not contain $.");if(e.includes("_"))throw new Error("Wrapper must not contain _.")}}}else{if(a.includes("$"))throw new Error("Invalid lifecycle marker.");if(a.match(/(?:^|[^_])_([a-z][A-Za-z0-9]*)$/))throw new Error("Wrapper without lifecycle is forbidden.")}if(u.includes("$$$$"))throw new Error("Lifecycle marker overflow.");const d=u.indexOf("__"),m=u.lastIndexOf("__");if(-1!==d&&d!==m)throw new Error("Export delimiter must appear at most once.");if(u.startsWith("__")||u.endsWith("__"))throw new Error("Malformed export segment.");let g=u,w=null;if(-1!==d){if(g=u.slice(0,d),w=u.slice(d+2),!w)throw new Error("Export must be non-empty.");if(w.includes("_"))throw new Error("Export must not contain _.");if(w.includes("$"))throw new Error("Export must not contain $.")}if(!g)throw new Error("moduleName must be non-empty.");if(g.startsWith("_")||g.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(g.includes("__"))throw new Error("moduleName must not contain __.");if(g.includes("$"))throw new Error("moduleName must not contain $.");let h=e.AS_IS;null!==w?h=e.FACTORY:p===t.SINGLETON?(w="default",h=e.FACTORY):p===t.TRANSIENT&&(h=e.FACTORY,null===w&&(w="default"));const $=r.create({moduleName:g,platform:l,exportName:w,composition:h,life:p,wrappers:f,origin:s});return n&&n.log(`Parser.parse: produced='${$.platform}::${$.moduleName}'.`),$},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},o=new f;return o.prefix="string"==typeof t.prefix?t.prefix:void 0,o.target="string"==typeof t.target?t.target:void 0,o.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(o)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const o=t&&"object"==typeof t?t:{},r=new d,n=Array.isArray(o.namespaces)?o.namespaces:[];return r.namespaces=n.map(t=>e.create(t)),r.nodeModulesRoot="string"==typeof o.nodeModulesRoot?o.nodeModulesRoot:void 0,Object.freeze(r.namespaces),Object.freeze(r)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:o=null}){const r=new Map,n=e;let i;const s=t,a=o,l=function(e,t){if("node"===e){const e=`node:${t}`;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const o=function(e){let t=null,o=-1;const r=i.namespaces;for(const n of r){const r=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(r)} module='${e}'.`),r&&n.prefix.length>o&&(t=n,o=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),r=t.slice(o.prefix.length).split("_").join("/"),n=(s=r,(l=o.defaultExt)?s.endsWith(l)?s:`${s}${l}`:s);var s,l;const c=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${c}'.`),c};this.resolve=async function(e){var t;await Promise.resolve(),i||(i={nodeModulesRoot:(t=n).nodeModulesRoot,namespaces:t.namespaces.map(e=>({prefix:e.prefix,target:e.target,defaultExt:e.defaultExt}))});const o=e.platform,c=e.moduleName,p=`${o}::${c}`;if(r.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),r.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=l(o,c);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}class w{constructor({parser:e,resolver:t,logger:o=null}){const r=o,n=async function(o,i,s,a){const l=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(s.has(l)){const e=[...a,l].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const c=function(e){return`${e.platform}::${e.moduleName}`}(o);if(!i.has(c)){s.add(l),a.push(l);try{const l=await t.resolve(o);r&&r.log(`GraphResolver.walk: resolved '${c}'.`),i.set(c,{depId:o,namespace:l});const p=Reflect.get(l,"__deps__");if(void 0===p)return;const f=p;for(const[,t]of Object.entries(f)){const o=t,l=e.parse(o);r&&r.log(`GraphResolver.walk: edge '${c}' -> '${l.platform}::${l.moduleName}'.`),await n(l,i,s,a)}}finally{a.pop(),s.delete(l)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await n(e,t,o,[]),t}}}class h{constructor(){this.instantiate=function(t,o,r){const n=function(e,t){if(null===e.exportName)return t;if(!(e.exportName in t))throw new Error(`Export '${e.exportName}' is not found in module namespace.`);return t[e.exportName]}(t,o);if(t.composition===e.AS_IS)return n;if(t.composition===e.FACTORY){if("function"!=typeof n)throw new Error("Factory composition requires a callable export.");const e=n;let t;if(function(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}(e)){t=new e(r)}else{t=e(r)}if(t instanceof Promise)throw new Error("Factory composition must return synchronously (non-Promise).");return t}throw new Error(`Unsupported composition mode: ${String(t.composition)}.`)}}}class ${constructor(o=null){const r=new Map,n=o;this.apply=function(o,i){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),i();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),i();if(o.life===t.SINGLETON){const e=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(r.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),r.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=i();return r.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),i()}}}class y{constructor(){const e=function(e){return"function"==typeof e};this.execute=function(t,o,r){let n=o;const i=t.wrappers;for(const t of i){if(!(t in r))throw new Error(`Wrapper '${t}' is not found in module namespace.`);const o=r[t];if(!e(o))throw new Error(`Wrapper '${t}' must be callable.`);if(n=o(n),n instanceof Promise)throw new Error(`Wrapper '${t}' must return synchronously (non-Promise).`)}return n}}}class N{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,o){console.error(`${t} ${e}`),o instanceof Error?console.error(o.stack??o.message):void 0!==o&&console.error(o)}}}const E=Object.freeze({log(){},error(){}});class x{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map,i=new WeakMap;let s=!1,a=!1,l=new p;const c=new m;let f,u,d,x=E;const C=new h,v=new y,b=function(e){return`${e.platform}::${e.moduleName}`},_=function(e){const t=null===e.exportName?"":e.exportName,o=null===e.life?"":e.life,r=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,o,r].join("::")},I=function(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;if("[object Module]"===Object.prototype.toString.call(e))return e;if(Object.isFrozen(e))return e;try{Object.freeze(e)}catch(e){x.log(`Container.freeze: skipped (${String(e)}).`)}return e},R=function(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;const o=e;if(i.has(o))return i.get(o);try{return Reflect.get(o,"then"),e}catch{const e=new Proxy(o,{get(e,t,o){if("then"!==t)return Reflect.get(e,t,o)}});return i.set(o,e),e}},j=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},A=function(e){a&&x.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){j(),A("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){j(),A("addPostprocess()."),o.push(e)},this.setParser=function(e){j(),l=e,"function"==typeof l.setLogger&&l.setLogger(a?x:null),A("setParser().")},this.addNamespaceRoot=function(e,t,o){j(),A(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){j(),A("enableTestMode()."),s=!0},this.enableLogging=function(){j(),a||(a=!0,x=new N,"function"==typeof l.setLogger&&l.setLogger(x),x.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(j(),A(`register('${e}').`),!0!==s)throw new Error("Container test mode is disabled.");const o=l.parse(e);n.set(_(o),t)},this.get=async function(i){if("failed"===e)throw x.error(`Container.get: rejected in failed state cdc='${i}'.`),new Error("Container is in failed state.");let a="start";try{x.log(`Container.get: cdc='${i}'.`),function(){if("notConfigured"!==e)return;x.log("Container.transition: notConfigured -> operational."),e="operational";const t=c.create({namespaces:r});"function"==typeof l.setLogger&&l.setLogger(x),f=new g({config:t,logger:x}),u=new w({parser:l,resolver:f,logger:x}),d=new $(x)}(),x.log(`Container.state: '${e}'.`),a="parse",x.log("Container.pipeline: parse:entry.");const p=l.parse(i);x.log(`Container.pipeline: parse:exit '${p.platform}::${p.moduleName}'.`),a="preprocess",x.log("Container.pipeline: preprocess:entry.");const m=function(e){let o=e;for(const e of t)o=e(o);return o}(p);if(x.log(`Container.pipeline: preprocess:exit '${m.platform}::${m.moduleName}'.`),!0===s){a="mock",x.log("Container.pipeline: mock-lookup:entry.");const e=_(m);if(n.has(e)){x.log(`Container.pipeline: mock-lookup:hit '${e}'.`),a="freeze",x.log("Container.pipeline: freeze:entry.");const t=I(n.get(e));return x.log("Container.pipeline: freeze:exit."),x.log("Container.pipeline: return:success."),R(t)}x.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else x.log("Container.pipeline: mock-lookup:disabled.");a="resolve",x.log("Container.pipeline: resolve:entry.");const h=await u.resolve(m);x.log(`Container.pipeline: resolve:exit nodes=${h.size}.`);const y=new Map,N=function(e){if(y.has(e))return y.get(e);if(!h.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=h.get(e);a="lifecycle",x.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=d.apply(t.depId,function(){a="instantiate",x.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},r=function(e){const t=Reflect.get(e,"__deps__");return void 0===t?{}:t}(t.namespace);for(const[t,o]of Object.entries(r)){const r=o,n=l.parse(r);e[t]=N(b(n))}const n=C.instantiate(t.depId,t.namespace,e);x.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),a="postprocess",x.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=function(e){let t=e;for(const e of o)t=e(t);return t}(n);x.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const s=v.execute(t.depId,i,t.namespace);a="freeze",x.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const c=I(s);return x.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),c});return x.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),y.set(e,r),r},E=N(b(m));return x.log("Container.pipeline: return:success."),R(E)}catch(t){throw x.error(`Container.pipeline: failed at stage='${a}'.`,t),x.log("Container.transition: operational -> failed."),e="failed",t}}}}export{x as default};
|
|
1
|
+
var e=Object.freeze({AS_IS:"A",FACTORY:"F"});var t=Object.freeze({SINGLETON:"S",TRANSIENT:"T"});var o=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const r=o.TEQ,n=e.AS_IS,i=new Set(Object.values(o)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let l=class{moduleName;platform;exportName;composition;life;wrappers;origin},c=class{create(e){const t=e&&"object"==typeof e?e:{},o=new l;o.moduleName="string"==typeof t.moduleName?t.moduleName:"";const c="string"==typeof t.platform?t.platform:void 0;o.platform=c&&i.has(c)?c:r;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),o.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;o.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return o.life=u&&a.has(u)?u:null,o.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],o.origin="string"==typeof t.origin?t.origin:"",Object.freeze(o.wrappers),Object.freeze(o)}};class p{constructor(){const r=new c;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("CDC must be a string.");if(0===i.length)throw new Error("CDC must be non-empty.");if(!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(i))throw new Error("CDC must satisfy AsciiCdcIdentifier.");const s=i;let a=i,l=o.TEQ;if(a.startsWith("node_"))l=o.NODE,a=a.slice(5);else if(a.startsWith("npm_"))l=o.NPM,a=a.slice(4);else if(a.startsWith("teq_"))throw new Error("Explicit teq_ prefix is forbidden.");if(0===a.length)throw new Error("moduleName must be non-empty.");const c=a.match(/(\${1,3})(?:_([A-Za-z0-9]+(?:_[A-Za-z0-9]+)*))?$/);let p=null,f=[],u=a;if(c){const e=c[1],o=c[2];if("$"===e)p=t.SINGLETON;else{if("$$"!==e&&"$$$"!==e)throw new Error("Lifecycle marker overflow.");p=t.TRANSIENT}if(u=a.slice(0,c.index),o){f=o.split("_");for(const e of f){if(!e)throw new Error("Wrapper must be non-empty.");if(e.includes("$"))throw new Error("Wrapper must not contain $.");if(e.includes("_"))throw new Error("Wrapper must not contain _.")}}}else{if(a.includes("$"))throw new Error("Invalid lifecycle marker.");if(a.match(/(?:^|[^_])_([a-z][A-Za-z0-9]*)$/))throw new Error("Wrapper without lifecycle is forbidden.")}if(u.includes("$$$$"))throw new Error("Lifecycle marker overflow.");const d=u.indexOf("__"),m=u.lastIndexOf("__");if(-1!==d&&d!==m)throw new Error("Export delimiter must appear at most once.");if(u.startsWith("__")||u.endsWith("__"))throw new Error("Malformed export segment.");let g=u,w=null;if(-1!==d){if(g=u.slice(0,d),w=u.slice(d+2),!w)throw new Error("Export must be non-empty.");if(w.includes("_"))throw new Error("Export must not contain _.");if(w.includes("$"))throw new Error("Export must not contain $.")}if(!g)throw new Error("moduleName must be non-empty.");if(g.startsWith("_")||g.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(g.includes("__"))throw new Error("moduleName must not contain __.");if(g.includes("$"))throw new Error("moduleName must not contain $.");let h=e.AS_IS;null!==w?h=e.FACTORY:p===t.SINGLETON?(w="default",h=e.FACTORY):p===t.TRANSIENT&&(h=e.FACTORY,null===w&&(w="default"));const $=r.create({moduleName:g,platform:l,exportName:w,composition:h,life:p,wrappers:f,origin:s});return n&&n.log(`Parser.parse: produced='${$.platform}::${$.moduleName}'.`),$},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},o=new f;return o.prefix="string"==typeof t.prefix?t.prefix:void 0,o.target="string"==typeof t.target?t.target:void 0,o.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(o)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const o=t&&"object"==typeof t?t:{},r=new d,n=Array.isArray(o.namespaces)?o.namespaces:[];return r.namespaces=n.map(t=>e.create(t)),r.nodeModulesRoot="string"==typeof o.nodeModulesRoot?o.nodeModulesRoot:void 0,Object.freeze(r.namespaces),Object.freeze(r)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:o=null}){const r=new Map,n=e;let i;const s=t,a=o,l=function(e,t){if("node"===e){const e=`node:${t}`;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const o=function(e){let t=null,o=-1;const r=i.namespaces;for(const n of r){const r=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(r)} module='${e}'.`),r&&n.prefix.length>o&&(t=n,o=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),r=t.slice(o.prefix.length).split("_").join("/"),n=(s=r,(l=o.defaultExt)?s.endsWith(l)?s:`${s}${l}`:s);var s,l;const c=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${c}'.`),c};this.resolve=async function(e){var t;await Promise.resolve(),i||(i={nodeModulesRoot:(t=n).nodeModulesRoot,namespaces:t.namespaces.map(e=>({prefix:e.prefix,target:e.target,defaultExt:e.defaultExt}))});const o=e.platform,c=e.moduleName,p=`${o}::${c}`;if(r.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),r.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=l(o,c);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}class w{constructor({parser:e,resolver:t,logger:o=null}){const r=o,n=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")},i=async function(o,s,a,l){const c=n(o);if(a.has(c)){const e=[...l,c].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const p=n(o);if(!s.has(p)){a.add(c),l.push(c);try{const n=await t.resolve(o);r&&r.log(`GraphResolver.walk: resolved '${p}'.`),s.set(p,{depId:o,namespace:n});const c=Reflect.get(n,"__deps__");if(void 0===c)return;const f=c;for(const[,t]of Object.entries(f)){const o=t,n=e.parse(o);r&&r.log(`GraphResolver.walk: edge '${p}' -> '${n.platform}::${n.moduleName}'.`),await i(n,s,a,l)}}finally{l.pop(),a.delete(c)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await i(e,t,o,[]),t}}}class h{constructor(){this.instantiate=function(t,o,r){const n=function(e,t){if(null===e.exportName)return t;if(!(e.exportName in t))throw new Error(`Export '${e.exportName}' is not found in module namespace.`);return t[e.exportName]}(t,o);if(t.composition===e.AS_IS)return n;if(t.composition===e.FACTORY){if("function"!=typeof n)throw new Error("Factory composition requires a callable export.");const e=n;let t;if(function(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}(e)){t=new e(r)}else{t=e(r)}if(t instanceof Promise)throw new Error("Factory composition must return synchronously (non-Promise).");return t}throw new Error(`Unsupported composition mode: ${String(t.composition)}.`)}}}class ${constructor(o=null){const r=new Map,n=o;this.apply=function(o,i){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),i();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),i();if(o.life===t.SINGLETON){const e=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(r.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),r.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=i();return r.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),i()}}}class y{constructor(){const e=function(e){return"function"==typeof e};this.execute=function(t,o,r){let n=o;const i=t.wrappers;for(const t of i){if(!(t in r))throw new Error(`Wrapper '${t}' is not found in module namespace.`);const o=r[t];if(!e(o))throw new Error(`Wrapper '${t}' must be callable.`);if(n=o(n),n instanceof Promise)throw new Error(`Wrapper '${t}' must return synchronously (non-Promise).`)}return n}}}class N{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,o){console.error(`${t} ${e}`),o instanceof Error?console.error(o.stack??o.message):void 0!==o&&console.error(o)}}}const E=Object.freeze({log(){},error(){}});class x{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map,i=new WeakMap;let s=!1,a=!1,l=new p;const c=new m;let f,u,d,x=E;const C=new h,v=new y,b=function(e){const t=null===e.exportName?"":e.exportName,o=null===e.life?"":e.life,r=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,o,r].join("::")},_=function(e){return b(e)},I=function(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;if("[object Module]"===Object.prototype.toString.call(e))return e;if(Object.isFrozen(e))return e;try{Object.freeze(e)}catch(e){x.log(`Container.freeze: skipped (${String(e)}).`)}return e},R=function(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;const o=e;if(i.has(o))return i.get(o);try{return Reflect.get(o,"then"),e}catch{const e=new Proxy(o,{get(e,t,o){if("then"!==t)return Reflect.get(e,t,o)}});return i.set(o,e),e}},j=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},A=function(e){a&&x.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){j(),A("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){j(),A("addPostprocess()."),o.push(e)},this.setParser=function(e){j(),l=e,"function"==typeof l.setLogger&&l.setLogger(a?x:null),A("setParser().")},this.addNamespaceRoot=function(e,t,o){j(),A(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){j(),A("enableTestMode()."),s=!0},this.enableLogging=function(){j(),a||(a=!0,x=new N,"function"==typeof l.setLogger&&l.setLogger(x),x.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(j(),A(`register('${e}').`),!0!==s)throw new Error("Container test mode is disabled.");const o=l.parse(e);n.set(_(o),t)},this.get=async function(i){if("failed"===e)throw x.error(`Container.get: rejected in failed state cdc='${i}'.`),new Error("Container is in failed state.");let a="start";try{x.log(`Container.get: cdc='${i}'.`),function(){if("notConfigured"!==e)return;x.log("Container.transition: notConfigured -> operational."),e="operational";const t=c.create({namespaces:r});"function"==typeof l.setLogger&&l.setLogger(x),f=new g({config:t,logger:x}),u=new w({parser:l,resolver:f,logger:x}),d=new $(x)}(),x.log(`Container.state: '${e}'.`),a="parse",x.log("Container.pipeline: parse:entry.");const p=l.parse(i);x.log(`Container.pipeline: parse:exit '${p.platform}::${p.moduleName}'.`),a="preprocess",x.log("Container.pipeline: preprocess:entry.");const m=function(e){let o=e;for(const e of t)o=e(o);return o}(p);if(x.log(`Container.pipeline: preprocess:exit '${m.platform}::${m.moduleName}'.`),!0===s){a="mock",x.log("Container.pipeline: mock-lookup:entry.");const e=_(m);if(n.has(e)){x.log(`Container.pipeline: mock-lookup:hit '${e}'.`),a="freeze",x.log("Container.pipeline: freeze:entry.");const t=I(n.get(e));return x.log("Container.pipeline: freeze:exit."),x.log("Container.pipeline: return:success."),R(t)}x.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else x.log("Container.pipeline: mock-lookup:disabled.");a="resolve",x.log("Container.pipeline: resolve:entry.");const h=await u.resolve(m);x.log(`Container.pipeline: resolve:exit nodes=${h.size}.`);const y=new Map,N=function(e){if(y.has(e))return y.get(e);if(!h.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=h.get(e);a="lifecycle",x.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=d.apply(t.depId,function(){a="instantiate",x.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},r=function(e){const t=Reflect.get(e,"__deps__");return void 0===t?{}:t}(t.namespace);for(const[t,o]of Object.entries(r)){const r=o,n=l.parse(r);e[t]=N(b(n))}const n=C.instantiate(t.depId,t.namespace,e);x.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),a="postprocess",x.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=function(e){let t=e;for(const e of o)t=e(t);return t}(n);x.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const s=v.execute(t.depId,i,t.namespace);a="freeze",x.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const c=I(s);return x.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),c});return x.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),y.set(e,r),r},E=N(b(m));return x.log("Container.pipeline: return:success."),R(E)}catch(t){throw x.error(`Container.pipeline: failed at stage='${a}'.`,t),x.log("Container.transition: operational -> failed."),e="failed",t}}}}export{x 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=Object.freeze({AS_IS:"A",FACTORY:"F"});var t=Object.freeze({SINGLETON:"S",TRANSIENT:"T"});var o=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const r=o.TEQ,n=e.AS_IS,i=new Set(Object.values(o)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let l=class{moduleName;platform;exportName;composition;life;wrappers;origin},c=class{create(e){const t=e&&"object"==typeof e?e:{},o=new l;o.moduleName="string"==typeof t.moduleName?t.moduleName:"";const c="string"==typeof t.platform?t.platform:void 0;o.platform=c&&i.has(c)?c:r;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),o.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;o.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return o.life=u&&a.has(u)?u:null,o.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],o.origin="string"==typeof t.origin?t.origin:"",Object.freeze(o.wrappers),Object.freeze(o)}};class p{constructor(){const r=new c;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("CDC must be a string.");if(0===i.length)throw new Error("CDC must be non-empty.");if(!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(i))throw new Error("CDC must satisfy AsciiCdcIdentifier.");const s=i;let a=i,l=o.TEQ;if(a.startsWith("node_"))l=o.NODE,a=a.slice(5);else if(a.startsWith("npm_"))l=o.NPM,a=a.slice(4);else if(a.startsWith("teq_"))throw new Error("Explicit teq_ prefix is forbidden.");if(0===a.length)throw new Error("moduleName must be non-empty.");const c=a.match(/(\${1,3})(?:_([A-Za-z0-9]+(?:_[A-Za-z0-9]+)*))?$/);let p=null,f=[],u=a;if(c){const e=c[1],o=c[2];if("$"===e)p=t.SINGLETON;else{if("$$"!==e&&"$$$"!==e)throw new Error("Lifecycle marker overflow.");p=t.TRANSIENT}if(u=a.slice(0,c.index),o){f=o.split("_");for(const e of f){if(!e)throw new Error("Wrapper must be non-empty.");if(e.includes("$"))throw new Error("Wrapper must not contain $.");if(e.includes("_"))throw new Error("Wrapper must not contain _.")}}}else{if(a.includes("$"))throw new Error("Invalid lifecycle marker.");if(a.match(/(?:^|[^_])_([a-z][A-Za-z0-9]*)$/))throw new Error("Wrapper without lifecycle is forbidden.")}if(u.includes("$$$$"))throw new Error("Lifecycle marker overflow.");const d=u.indexOf("__"),m=u.lastIndexOf("__");if(-1!==d&&d!==m)throw new Error("Export delimiter must appear at most once.");if(u.startsWith("__")||u.endsWith("__"))throw new Error("Malformed export segment.");let g=u,w=null;if(-1!==d){if(g=u.slice(0,d),w=u.slice(d+2),!w)throw new Error("Export must be non-empty.");if(w.includes("_"))throw new Error("Export must not contain _.");if(w.includes("$"))throw new Error("Export must not contain $.")}if(!g)throw new Error("moduleName must be non-empty.");if(g.startsWith("_")||g.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(g.includes("__"))throw new Error("moduleName must not contain __.");if(g.includes("$"))throw new Error("moduleName must not contain $.");let h=e.AS_IS;null!==w?h=e.FACTORY:p===t.SINGLETON?(w="default",h=e.FACTORY):p===t.TRANSIENT&&(h=e.FACTORY,null===w&&(w="default"));const $=r.create({moduleName:g,platform:l,exportName:w,composition:h,life:p,wrappers:f,origin:s});return n&&n.log(`Parser.parse: produced='${$.platform}::${$.moduleName}'.`),$},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},o=new f;return o.prefix="string"==typeof t.prefix?t.prefix:void 0,o.target="string"==typeof t.target?t.target:void 0,o.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(o)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const o=t&&"object"==typeof t?t:{},r=new d,n=Array.isArray(o.namespaces)?o.namespaces:[];return r.namespaces=n.map(t=>e.create(t)),r.nodeModulesRoot="string"==typeof o.nodeModulesRoot?o.nodeModulesRoot:void 0,Object.freeze(r.namespaces),Object.freeze(r)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:o=null}){const r=new Map,n=e;let i;const s=t,a=o,l=function(e,t){if("node"===e){const e=`node:${t}`;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const o=function(e){let t=null,o=-1;const r=i.namespaces;for(const n of r){const r=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(r)} module='${e}'.`),r&&n.prefix.length>o&&(t=n,o=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),r=t.slice(o.prefix.length).split("_").join("/"),n=(s=r,(l=o.defaultExt)?s.endsWith(l)?s:`${s}${l}`:s);var s,l;const c=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${c}'.`),c};this.resolve=async function(e){var t;await Promise.resolve(),i||(i={nodeModulesRoot:(t=n).nodeModulesRoot,namespaces:t.namespaces.map(e=>({prefix:e.prefix,target:e.target,defaultExt:e.defaultExt}))});const o=e.platform,c=e.moduleName,p=`${o}::${c}`;if(r.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),r.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=l(o,c);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}class w{constructor({parser:e,resolver:t,logger:o=null}){const r=o,n=async function(o,i,s,a){const l=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(s.has(l)){const e=[...a,l].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const c=function(e){return`${e.platform}::${e.moduleName}`}(o);if(!i.has(c)){s.add(l),a.push(l);try{const l=await t.resolve(o);r&&r.log(`GraphResolver.walk: resolved '${c}'.`),i.set(c,{depId:o,namespace:l});const p=Reflect.get(l,"__deps__");if(void 0===p)return;const f=p;for(const[,t]of Object.entries(f)){const o=t,l=e.parse(o);r&&r.log(`GraphResolver.walk: edge '${c}' -> '${l.platform}::${l.moduleName}'.`),await n(l,i,s,a)}}finally{a.pop(),s.delete(l)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await n(e,t,o,[]),t}}}class h{constructor(){this.instantiate=function(t,o,r){const n=function(e,t){if(null===e.exportName)return t;if(!(e.exportName in t))throw new Error(`Export '${e.exportName}' is not found in module namespace.`);return t[e.exportName]}(t,o);if(t.composition===e.AS_IS)return n;if(t.composition===e.FACTORY){if("function"!=typeof n)throw new Error("Factory composition requires a callable export.");const e=n;let t;if(function(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}(e)){t=new e(r)}else{t=e(r)}if(t instanceof Promise)throw new Error("Factory composition must return synchronously (non-Promise).");return t}throw new Error(`Unsupported composition mode: ${String(t.composition)}.`)}}}class ${constructor(o=null){const r=new Map,n=o;this.apply=function(o,i){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),i();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),i();if(o.life===t.SINGLETON){const e=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(r.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),r.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=i();return r.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),i()}}}class y{constructor(){const e=function(e){return"function"==typeof e};this.execute=function(t,o,r){let n=o;const i=t.wrappers;for(const t of i){if(!(t in r))throw new Error(`Wrapper '${t}' is not found in module namespace.`);const o=r[t];if(!e(o))throw new Error(`Wrapper '${t}' must be callable.`);if(n=o(n),n instanceof Promise)throw new Error(`Wrapper '${t}' must return synchronously (non-Promise).`)}return n}}}class N{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,o){console.error(`${t} ${e}`),o instanceof Error?console.error(o.stack??o.message):void 0!==o&&console.error(o)}}}const E=Object.freeze({log(){},error(){}});return class{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map,i=new WeakMap;let s=!1,a=!1,l=new p;const c=new m;let f,u,d,x=E;const C=new h,b=new y,v=function(e){return`${e.platform}::${e.moduleName}`},_=function(e){const t=null===e.exportName?"":e.exportName,o=null===e.life?"":e.life,r=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,o,r].join("::")},I=function(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;if("[object Module]"===Object.prototype.toString.call(e))return e;if(Object.isFrozen(e))return e;try{Object.freeze(e)}catch(e){x.log(`Container.freeze: skipped (${String(e)}).`)}return e},R=function(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;const o=e;if(i.has(o))return i.get(o);try{return Reflect.get(o,"then"),e}catch{const e=new Proxy(o,{get(e,t,o){if("then"!==t)return Reflect.get(e,t,o)}});return i.set(o,e),e}},j=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},A=function(e){a&&x.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){j(),A("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){j(),A("addPostprocess()."),o.push(e)},this.setParser=function(e){j(),l=e,"function"==typeof l.setLogger&&l.setLogger(a?x:null),A("setParser().")},this.addNamespaceRoot=function(e,t,o){j(),A(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){j(),A("enableTestMode()."),s=!0},this.enableLogging=function(){j(),a||(a=!0,x=new N,"function"==typeof l.setLogger&&l.setLogger(x),x.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(j(),A(`register('${e}').`),!0!==s)throw new Error("Container test mode is disabled.");const o=l.parse(e);n.set(_(o),t)},this.get=async function(i){if("failed"===e)throw x.error(`Container.get: rejected in failed state cdc='${i}'.`),new Error("Container is in failed state.");let a="start";try{x.log(`Container.get: cdc='${i}'.`),function(){if("notConfigured"!==e)return;x.log("Container.transition: notConfigured -> operational."),e="operational";const t=c.create({namespaces:r});"function"==typeof l.setLogger&&l.setLogger(x),f=new g({config:t,logger:x}),u=new w({parser:l,resolver:f,logger:x}),d=new $(x)}(),x.log(`Container.state: '${e}'.`),a="parse",x.log("Container.pipeline: parse:entry.");const p=l.parse(i);x.log(`Container.pipeline: parse:exit '${p.platform}::${p.moduleName}'.`),a="preprocess",x.log("Container.pipeline: preprocess:entry.");const m=function(e){let o=e;for(const e of t)o=e(o);return o}(p);if(x.log(`Container.pipeline: preprocess:exit '${m.platform}::${m.moduleName}'.`),!0===s){a="mock",x.log("Container.pipeline: mock-lookup:entry.");const e=_(m);if(n.has(e)){x.log(`Container.pipeline: mock-lookup:hit '${e}'.`),a="freeze",x.log("Container.pipeline: freeze:entry.");const t=I(n.get(e));return x.log("Container.pipeline: freeze:exit."),x.log("Container.pipeline: return:success."),R(t)}x.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else x.log("Container.pipeline: mock-lookup:disabled.");a="resolve",x.log("Container.pipeline: resolve:entry.");const h=await u.resolve(m);x.log(`Container.pipeline: resolve:exit nodes=${h.size}.`);const y=new Map,N=function(e){if(y.has(e))return y.get(e);if(!h.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=h.get(e);a="lifecycle",x.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=d.apply(t.depId,function(){a="instantiate",x.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},r=function(e){const t=Reflect.get(e,"__deps__");return void 0===t?{}:t}(t.namespace);for(const[t,o]of Object.entries(r)){const r=o,n=l.parse(r);e[t]=N(v(n))}const n=C.instantiate(t.depId,t.namespace,e);x.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),a="postprocess",x.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=function(e){let t=e;for(const e of o)t=e(t);return t}(n);x.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const s=b.execute(t.depId,i,t.namespace);a="freeze",x.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const c=I(s);return x.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),c});return x.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),y.set(e,r),r},E=N(v(m));return x.log("Container.pipeline: return:success."),R(E)}catch(t){throw x.error(`Container.pipeline: failed at stage='${a}'.`,t),x.log("Container.transition: operational -> failed."),e="failed",t}}}}});
|
|
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=Object.freeze({AS_IS:"A",FACTORY:"F"});var t=Object.freeze({SINGLETON:"S",TRANSIENT:"T"});var o=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const r=o.TEQ,n=e.AS_IS,i=new Set(Object.values(o)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let l=class{moduleName;platform;exportName;composition;life;wrappers;origin},c=class{create(e){const t=e&&"object"==typeof e?e:{},o=new l;o.moduleName="string"==typeof t.moduleName?t.moduleName:"";const c="string"==typeof t.platform?t.platform:void 0;o.platform=c&&i.has(c)?c:r;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),o.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;o.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return o.life=u&&a.has(u)?u:null,o.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],o.origin="string"==typeof t.origin?t.origin:"",Object.freeze(o.wrappers),Object.freeze(o)}};class p{constructor(){const r=new c;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("CDC must be a string.");if(0===i.length)throw new Error("CDC must be non-empty.");if(!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(i))throw new Error("CDC must satisfy AsciiCdcIdentifier.");const s=i;let a=i,l=o.TEQ;if(a.startsWith("node_"))l=o.NODE,a=a.slice(5);else if(a.startsWith("npm_"))l=o.NPM,a=a.slice(4);else if(a.startsWith("teq_"))throw new Error("Explicit teq_ prefix is forbidden.");if(0===a.length)throw new Error("moduleName must be non-empty.");const c=a.match(/(\${1,3})(?:_([A-Za-z0-9]+(?:_[A-Za-z0-9]+)*))?$/);let p=null,f=[],u=a;if(c){const e=c[1],o=c[2];if("$"===e)p=t.SINGLETON;else{if("$$"!==e&&"$$$"!==e)throw new Error("Lifecycle marker overflow.");p=t.TRANSIENT}if(u=a.slice(0,c.index),o){f=o.split("_");for(const e of f){if(!e)throw new Error("Wrapper must be non-empty.");if(e.includes("$"))throw new Error("Wrapper must not contain $.");if(e.includes("_"))throw new Error("Wrapper must not contain _.")}}}else{if(a.includes("$"))throw new Error("Invalid lifecycle marker.");if(a.match(/(?:^|[^_])_([a-z][A-Za-z0-9]*)$/))throw new Error("Wrapper without lifecycle is forbidden.")}if(u.includes("$$$$"))throw new Error("Lifecycle marker overflow.");const d=u.indexOf("__"),m=u.lastIndexOf("__");if(-1!==d&&d!==m)throw new Error("Export delimiter must appear at most once.");if(u.startsWith("__")||u.endsWith("__"))throw new Error("Malformed export segment.");let g=u,w=null;if(-1!==d){if(g=u.slice(0,d),w=u.slice(d+2),!w)throw new Error("Export must be non-empty.");if(w.includes("_"))throw new Error("Export must not contain _.");if(w.includes("$"))throw new Error("Export must not contain $.")}if(!g)throw new Error("moduleName must be non-empty.");if(g.startsWith("_")||g.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(g.includes("__"))throw new Error("moduleName must not contain __.");if(g.includes("$"))throw new Error("moduleName must not contain $.");let h=e.AS_IS;null!==w?h=e.FACTORY:p===t.SINGLETON?(w="default",h=e.FACTORY):p===t.TRANSIENT&&(h=e.FACTORY,null===w&&(w="default"));const $=r.create({moduleName:g,platform:l,exportName:w,composition:h,life:p,wrappers:f,origin:s});return n&&n.log(`Parser.parse: produced='${$.platform}::${$.moduleName}'.`),$},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},o=new f;return o.prefix="string"==typeof t.prefix?t.prefix:void 0,o.target="string"==typeof t.target?t.target:void 0,o.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(o)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const o=t&&"object"==typeof t?t:{},r=new d,n=Array.isArray(o.namespaces)?o.namespaces:[];return r.namespaces=n.map(t=>e.create(t)),r.nodeModulesRoot="string"==typeof o.nodeModulesRoot?o.nodeModulesRoot:void 0,Object.freeze(r.namespaces),Object.freeze(r)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:o=null}){const r=new Map,n=e;let i;const s=t,a=o,l=function(e,t){if("node"===e){const e=`node:${t}`;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const o=function(e){let t=null,o=-1;const r=i.namespaces;for(const n of r){const r=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(r)} module='${e}'.`),r&&n.prefix.length>o&&(t=n,o=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),r=t.slice(o.prefix.length).split("_").join("/"),n=(s=r,(l=o.defaultExt)?s.endsWith(l)?s:`${s}${l}`:s);var s,l;const c=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${c}'.`),c};this.resolve=async function(e){var t;await Promise.resolve(),i||(i={nodeModulesRoot:(t=n).nodeModulesRoot,namespaces:t.namespaces.map(e=>({prefix:e.prefix,target:e.target,defaultExt:e.defaultExt}))});const o=e.platform,c=e.moduleName,p=`${o}::${c}`;if(r.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),r.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=l(o,c);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}class w{constructor({parser:e,resolver:t,logger:o=null}){const r=o,n=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")},i=async function(o,s,a,l){const c=n(o);if(a.has(c)){const e=[...l,c].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const p=n(o);if(!s.has(p)){a.add(c),l.push(c);try{const n=await t.resolve(o);r&&r.log(`GraphResolver.walk: resolved '${p}'.`),s.set(p,{depId:o,namespace:n});const c=Reflect.get(n,"__deps__");if(void 0===c)return;const f=c;for(const[,t]of Object.entries(f)){const o=t,n=e.parse(o);r&&r.log(`GraphResolver.walk: edge '${p}' -> '${n.platform}::${n.moduleName}'.`),await i(n,s,a,l)}}finally{l.pop(),a.delete(c)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await i(e,t,o,[]),t}}}class h{constructor(){this.instantiate=function(t,o,r){const n=function(e,t){if(null===e.exportName)return t;if(!(e.exportName in t))throw new Error(`Export '${e.exportName}' is not found in module namespace.`);return t[e.exportName]}(t,o);if(t.composition===e.AS_IS)return n;if(t.composition===e.FACTORY){if("function"!=typeof n)throw new Error("Factory composition requires a callable export.");const e=n;let t;if(function(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}(e)){t=new e(r)}else{t=e(r)}if(t instanceof Promise)throw new Error("Factory composition must return synchronously (non-Promise).");return t}throw new Error(`Unsupported composition mode: ${String(t.composition)}.`)}}}class ${constructor(o=null){const r=new Map,n=o;this.apply=function(o,i){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),i();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),i();if(o.life===t.SINGLETON){const e=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(r.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),r.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=i();return r.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),i()}}}class y{constructor(){const e=function(e){return"function"==typeof e};this.execute=function(t,o,r){let n=o;const i=t.wrappers;for(const t of i){if(!(t in r))throw new Error(`Wrapper '${t}' is not found in module namespace.`);const o=r[t];if(!e(o))throw new Error(`Wrapper '${t}' must be callable.`);if(n=o(n),n instanceof Promise)throw new Error(`Wrapper '${t}' must return synchronously (non-Promise).`)}return n}}}class N{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,o){console.error(`${t} ${e}`),o instanceof Error?console.error(o.stack??o.message):void 0!==o&&console.error(o)}}}const E=Object.freeze({log(){},error(){}});return class{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map,i=new WeakMap;let s=!1,a=!1,l=new p;const c=new m;let f,u,d,x=E;const C=new h,b=new y,v=function(e){const t=null===e.exportName?"":e.exportName,o=null===e.life?"":e.life,r=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,o,r].join("::")},_=function(e){return v(e)},I=function(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;if("[object Module]"===Object.prototype.toString.call(e))return e;if(Object.isFrozen(e))return e;try{Object.freeze(e)}catch(e){x.log(`Container.freeze: skipped (${String(e)}).`)}return e},R=function(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;const o=e;if(i.has(o))return i.get(o);try{return Reflect.get(o,"then"),e}catch{const e=new Proxy(o,{get(e,t,o){if("then"!==t)return Reflect.get(e,t,o)}});return i.set(o,e),e}},j=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},A=function(e){a&&x.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){j(),A("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){j(),A("addPostprocess()."),o.push(e)},this.setParser=function(e){j(),l=e,"function"==typeof l.setLogger&&l.setLogger(a?x:null),A("setParser().")},this.addNamespaceRoot=function(e,t,o){j(),A(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){j(),A("enableTestMode()."),s=!0},this.enableLogging=function(){j(),a||(a=!0,x=new N,"function"==typeof l.setLogger&&l.setLogger(x),x.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(j(),A(`register('${e}').`),!0!==s)throw new Error("Container test mode is disabled.");const o=l.parse(e);n.set(_(o),t)},this.get=async function(i){if("failed"===e)throw x.error(`Container.get: rejected in failed state cdc='${i}'.`),new Error("Container is in failed state.");let a="start";try{x.log(`Container.get: cdc='${i}'.`),function(){if("notConfigured"!==e)return;x.log("Container.transition: notConfigured -> operational."),e="operational";const t=c.create({namespaces:r});"function"==typeof l.setLogger&&l.setLogger(x),f=new g({config:t,logger:x}),u=new w({parser:l,resolver:f,logger:x}),d=new $(x)}(),x.log(`Container.state: '${e}'.`),a="parse",x.log("Container.pipeline: parse:entry.");const p=l.parse(i);x.log(`Container.pipeline: parse:exit '${p.platform}::${p.moduleName}'.`),a="preprocess",x.log("Container.pipeline: preprocess:entry.");const m=function(e){let o=e;for(const e of t)o=e(o);return o}(p);if(x.log(`Container.pipeline: preprocess:exit '${m.platform}::${m.moduleName}'.`),!0===s){a="mock",x.log("Container.pipeline: mock-lookup:entry.");const e=_(m);if(n.has(e)){x.log(`Container.pipeline: mock-lookup:hit '${e}'.`),a="freeze",x.log("Container.pipeline: freeze:entry.");const t=I(n.get(e));return x.log("Container.pipeline: freeze:exit."),x.log("Container.pipeline: return:success."),R(t)}x.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else x.log("Container.pipeline: mock-lookup:disabled.");a="resolve",x.log("Container.pipeline: resolve:entry.");const h=await u.resolve(m);x.log(`Container.pipeline: resolve:exit nodes=${h.size}.`);const y=new Map,N=function(e){if(y.has(e))return y.get(e);if(!h.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=h.get(e);a="lifecycle",x.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=d.apply(t.depId,function(){a="instantiate",x.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},r=function(e){const t=Reflect.get(e,"__deps__");return void 0===t?{}:t}(t.namespace);for(const[t,o]of Object.entries(r)){const r=o,n=l.parse(r);e[t]=N(v(n))}const n=C.instantiate(t.depId,t.namespace,e);x.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),a="postprocess",x.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=function(e){let t=e;for(const e of o)t=e(t);return t}(n);x.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const s=b.execute(t.depId,i,t.namespace);a="freeze",x.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const c=I(s);return x.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),c});return x.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),y.set(e,r),r},E=N(v(m));return x.log("Container.pipeline: return:success."),R(E)}catch(t){throw x.error(`Container.pipeline: failed at stage='${a}'.`,t),x.log("Container.transition: operational -> failed."),e="failed",t}}}}});
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Resolve-stage graph builder.
|
|
5
5
|
*
|
|
6
6
|
* Recursively resolves module namespaces and their declared `__deps__`
|
|
7
|
-
* into a deterministic map keyed by
|
|
7
|
+
* into a deterministic map keyed by structural DepId identity.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -32,14 +32,6 @@ export default class TeqFw_Di_Container_Resolve_GraphResolver {
|
|
|
32
32
|
* @returns {string}
|
|
33
33
|
*/
|
|
34
34
|
const makeNodeKey = function (depId) {
|
|
35
|
-
return `${depId.platform}::${depId.moduleName}`;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {TeqFw_Di_DepId$DTO} depId
|
|
40
|
-
* @returns {string}
|
|
41
|
-
*/
|
|
42
|
-
const makeDepIdentity = function (depId) {
|
|
43
35
|
/** @type {string} */
|
|
44
36
|
const wrappers = Array.isArray(depId.wrappers) ? depId.wrappers.join('|') : '';
|
|
45
37
|
return [
|
|
@@ -61,7 +53,7 @@ export default class TeqFw_Di_Container_Resolve_GraphResolver {
|
|
|
61
53
|
*/
|
|
62
54
|
const walk = async function (depId, out, stack, chain) {
|
|
63
55
|
/** @type {string} */
|
|
64
|
-
const identity =
|
|
56
|
+
const identity = makeNodeKey(depId);
|
|
65
57
|
if (stack.has(identity)) {
|
|
66
58
|
/** @type {string} */
|
|
67
59
|
const cycle = [...chain, identity].join(' -> ');
|
package/src/Container.mjs
CHANGED
|
@@ -65,16 +65,6 @@ export default class TeqFw_Di_Container {
|
|
|
65
65
|
* @returns {string}
|
|
66
66
|
*/
|
|
67
67
|
const getKey = function (depId) {
|
|
68
|
-
return `${depId.platform}::${depId.moduleName}`;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Canonical structural identity excluding `origin`.
|
|
73
|
-
*
|
|
74
|
-
* @param {TeqFw_Di_DepId$DTO} depId
|
|
75
|
-
* @returns {string}
|
|
76
|
-
*/
|
|
77
|
-
const getMockKey = function (depId) {
|
|
78
68
|
const exportName = depId.exportName === null ? '' : depId.exportName;
|
|
79
69
|
const life = depId.life === null ? '' : depId.life;
|
|
80
70
|
const wrappers = Array.isArray(depId.wrappers) ? depId.wrappers.join('|') : '';
|
|
@@ -88,6 +78,16 @@ export default class TeqFw_Di_Container {
|
|
|
88
78
|
].join('::');
|
|
89
79
|
};
|
|
90
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Canonical structural identity excluding `origin`.
|
|
83
|
+
*
|
|
84
|
+
* @param {TeqFw_Di_DepId$DTO} depId
|
|
85
|
+
* @returns {string}
|
|
86
|
+
*/
|
|
87
|
+
const getMockKey = function (depId) {
|
|
88
|
+
return getKey(depId);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
91
|
/**
|
|
92
92
|
* Freezes values that support freezing.
|
|
93
93
|
*
|