@teqfw/di 2.7.0 → 2.8.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/ai/AGENTS.md CHANGED
@@ -1,62 +1,18 @@
1
- # AGENTS.md
1
+ # AI Package Interface (Legacy Pointer)
2
2
 
3
- Version: 20260606
3
+ Version: 20260730
4
4
 
5
5
  ## Purpose
6
6
 
7
- This file defines the `ai/` level for agent-facing package documentation included in the distributable package.
7
+ This legacy directory remains temporarily for compatibility. Do not add a second agent interface here; go to the distributable `teqfw-di` Agent Skill at `../skills/teqfw-di/SKILL.md` for current guidance.
8
8
 
9
- The `ai/` directory provides a compact machine-oriented interface for agents that need to understand and use the package correctly.
9
+ ## Structure
10
10
 
11
- ## Level Boundary
11
+ - `AGENTS.md` is repository navigation and is not an installed skill entry point.
12
+ - `../skills/teqfw-di/` is the distributable `teqfw-di` Agent Skill.
13
+ - `../skills/teqfw-di/SKILL.md` is the consumer entry point.
14
+ - `../skills/teqfw-di/references/` contains self-contained detailed consumer references.
12
15
 
13
- This level defines:
16
+ ## Authoring Boundary
14
17
 
15
- - what documents exist in `ai/`;
16
- - what each document is for;
17
- - how an agent should navigate this directory;
18
- - which documents describe supported usage.
19
-
20
- This level does not define:
21
-
22
- - repository organization;
23
- - development workflow;
24
- - testing strategy;
25
- - internal implementation details that are not part of the supported surface;
26
- - behavior not described by the documents in `ai/`.
27
-
28
- ## Level Map
29
-
30
- - `AGENTS.md` — entry point for this level; defines scope, navigation, and authority.
31
- - `concepts.md` — core concepts behind runtime linking and dependency contracts.
32
- - `container.md` — container lifecycle, state model, and resolution pipeline.
33
- - `dependency-id.md` — normative CDC grammar and interpretation rules.
34
- - `extensions.md` — preprocess hooks, postprocess hooks, and wrapper exports.
35
- - `package-api.ts` — machine-readable contract of the supported programmatic surface.
36
- - `usage.md` — canonical usage patterns and short integration recipes.
37
-
38
- ## Reading Guide
39
-
40
- Read documents by task:
41
-
42
- - for supported imports and public surface, start with `package-api.ts`;
43
- - for CDC syntax and meaning, read `dependency-id.md`;
44
- - for runtime behavior of the container, read `container.md`;
45
- - for extension behavior, read `extensions.md`;
46
- - for practical integration examples, read `usage.md`;
47
- - for conceptual orientation, read `concepts.md`.
48
-
49
- If the task is broad or unclear, read in this order:
50
-
51
- 1. `AGENTS.md`
52
- 2. `package-api.ts`
53
- 3. `usage.md`
54
- 4. `dependency-id.md`
55
- 5. `container.md`
56
- 6. remaining documents as needed
57
-
58
- ## Authority
59
-
60
- The documents in `ai/` define the supported agent-facing usage semantics of the package.
61
-
62
- Agents should rely on these documents for package use and should treat behavior not described here as undefined.
18
+ Keep the skill consumer-oriented and aligned with supported package behavior. Do not make the published skill depend on repository-only files or `ctx/`; its references must be loadable from an installed package. Product cognitive context remains authoritative for repository work, while the skill communicates correct use of the installed dependency.
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 r=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const o=r.TEQ,n=e.AS_IS,i=new Set(Object.values(r)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let c=class{moduleName;platform;exportName;composition;life;wrappers;origin},l=class{create(e){const t=e&&"object"==typeof e?e:{},r=new c;r.moduleName="string"==typeof t.moduleName?t.moduleName:"";const l="string"==typeof t.platform?t.platform:void 0;r.platform=l&&i.has(l)?l:o;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),r.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;r.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return r.life=u&&a.has(u)?u:null,r.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],r.origin="string"==typeof t.origin?t.origin:"",Object.freeze(r.wrappers),Object.freeze(r)}};class p{constructor(){const o=new l;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(!/^[\x00-\x7F]+$/.test(i))throw new Error("CDC must be ASCII.");const s=i,a=function(e){let t=r.TEQ;if(e.startsWith("node:"))return t=r.NODE,{platform:t,source:e.slice(5)};if(e.startsWith("npm:"))return t=r.NPM,{platform:t,source:e.slice(4)};if(e.startsWith("teq:"))throw new Error("Explicit teq: prefix is forbidden.");return{platform:t,source:e}}(i),c=a.platform,l=a.source;if(0===l.length)throw new Error("moduleName must be non-empty.");const p=function(e,o){let n=null,i=!1,s=[],a=e;const c=a.match(/(\${1,3})(?:_[a-z][0-9A-Za-z]*)*$/);if(c){const e=c[1],r=c[0].slice(e.length);if(i=!0,"$"===e)n=t.SINGLETON;else if("$$"===e)n=t.TRANSIENT;else{if("$$$"!==e)throw new Error("Lifecycle marker is invalid.");n=null}return a=a.slice(0,c.index),r.length>0&&(s=r.slice(1).split("_")),{core:a,life:n,lifecycleDeclared:i,wrappers:s}}if(e.includes("$"))throw new Error("Invalid lifecycle encoding.");if(o!==r.NODE&&/(?:^|[^_])_[a-z][0-9A-Za-z]*$/.test(e))throw new Error("Wrapper without lifecycle is forbidden.");return{core:a,life:n,lifecycleDeclared:i,wrappers:s}}(l,c),f=function(e){const t=e.indexOf("__"),r=e.lastIndexOf("__");if(-1!==t&&t!==r)throw new Error("Export delimiter must appear at most once.");if(e.startsWith("__")||e.endsWith("__"))throw new Error("Malformed export segment.");let o=e,n=null;if(-1!==t){if(o=e.slice(0,t),n=e.slice(t+2),!n)throw new Error("Export must be non-empty.");if(n.includes("_"))throw new Error("Export must not contain _.");if(n.includes("$"))throw new Error("Export must not contain $.")}return{moduleName:o,exportName:n}}(p.core);!function(e,t){if(!e)throw new Error("moduleName must be non-empty.");if(e.startsWith("_")||e.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(e.includes("__"))throw new Error("moduleName must not contain __.");if(e.includes("$"))throw new Error("moduleName must not contain $.");if(t!==r.NPM){if(t===r.NODE){if(!/^[A-Za-z_][$0-9A-Za-z_/-]*$/.test(e))throw new Error("node moduleName must satisfy the built-in specifier form.")}else if(!/^[A-Za-z_][$0-9A-Za-z_]*$/.test(e))throw new Error("moduleName must satisfy the canonical identifier form.")}else if(!/^[@A-Za-z_][$0-9A-Za-z_./-]*$/.test(e))throw new Error("npm moduleName must satisfy the package specifier form.")}(f.moduleName,c);let u=e.AS_IS,d=f.exportName;p.lifecycleDeclared&&(null===d&&(d="default"),u=e.FACTORY);const m=o.create({moduleName:f.moduleName,platform:c,exportName:d,composition:u,life:p.life,wrappers:p.wrappers,origin:s});return n&&n.log(`Parser.parse: produced='${m.platform}::${m.moduleName}'.`),m},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},r=new f;return r.prefix="string"==typeof t.prefix?t.prefix:void 0,r.target="string"==typeof t.target?t.target:void 0,r.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(r)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const r=t&&"object"==typeof t?t:{},o=new d,n=Array.isArray(r.namespaces)?r.namespaces:[];return o.namespaces=n.map(t=>e.create(t)),o.nodeModulesRoot="string"==typeof r.nodeModulesRoot?r.nodeModulesRoot:void 0,Object.freeze(o.namespaces),Object.freeze(o)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:r=null}){const o=new Map,n=e;let i;const s=t,a=r,c=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 r=function(e){let t=null,r=-1;const o=i.namespaces;for(const n of o){const o=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(o)} module='${e}'.`),o&&n.prefix.length>r&&(t=n,r=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),o=t.slice(r.prefix.length).split("_").join("/"),n=(s=o,(c=r.defaultExt)?s.endsWith(c)?s:`${s}${c}`:s);var s,c;const l=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(r.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${l}'.`),l};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 r=e.platform,l=e.moduleName,p=`${r}::${l}`;if(o.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),o.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=c(r,l);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();o.set(p,f);try{return await f}catch(e){throw o.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}function w(e){const t=null===e.exportName?"":e.exportName,r=null===e.life?"":e.life,o=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,r,o].join("::")}function h(e,t){const r=Reflect.get(e,"__deps__");if(void 0===r)return{};if(null===r||"object"!=typeof r||Array.isArray(r))throw new Error("__deps__ must be a plain object.");const o=null===t.exportName?"default":t.exportName,n=Reflect.get(r,o);if(null!=n&&"object"==typeof n&&!Array.isArray(n)){if(!Object.values(n).every(e=>"string"==typeof e))throw new Error("__deps__ export entries must map dependency names to CDC strings.");return n}if("default"===o){const e=Object.values(r);if(e.every(e=>"string"==typeof e))return r;if(e.every(e=>null!==e&&"object"==typeof e&&!Array.isArray(e)))return{};throw new Error("__deps__ must be either flat or export-scoped.")}return{}}class y{constructor({parser:e,resolver:t,logger:r=null}){const o=r,n=w,i=async function(r,s,a,c){const l=n(r);if(a.has(l)){const e=[...c,l].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const p=n(r);if(!s.has(p)){a.add(l),c.push(l);try{const n=await t.resolve(r);o&&o.log(`GraphResolver.walk: resolved '${p}'.`),s.set(p,{depId:r,namespace:n});const l=h(n,r);for(const t of Object.values(l)){const r=e.parse(t);o&&o.log(`GraphResolver.walk: edge '${p}' -> '${r.platform}::${r.moduleName}'.`),await i(r,s,a,c)}}finally{c.pop(),a.delete(l)}}};this.resolve=async function(e){const t=new Map,r=new Set;return await i(e,t,r,[]),t}}}class ${constructor(){this.instantiate=function(t,r,o){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,r);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(o)}else{t=e(o)}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 E{constructor(r=null){const o=new Map,n=r,i=w;this.apply=function(r,s){if(r.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${r.composition}' cache=skip.`),s();if(r.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),s();if(r.life===t.SINGLETON){const e=i(r);if(o.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),o.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=s();return o.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),s()}}}class N{constructor(){const e=function(e){return"function"==typeof e};this.execute=function(t,r,o){let n=r;const i=t.wrappers;for(const t of i){if(!(t in o))throw new Error(`Wrapper '${t}' is not found in module namespace.`);const r=o[t];if(!e(r))throw new Error(`Wrapper '${t}' must be callable.`);if(n=r(n),n instanceof Promise)throw new Error(`Wrapper '${t}' must return synchronously (non-Promise).`)}return n}}}const x=new WeakMap;function C(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;const r=e;if(x.has(r))return x.get(r);try{return Reflect.get(r,"then"),e}catch{const e=new Proxy(r,{get(e,t,r){if("then"!==t)return Reflect.get(e,t,r)}});return x.set(r,e),e}}class b{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,r){console.error(`${t} ${e}`),r instanceof Error?console.error(r.stack??r.message):void 0!==r&&console.error(r)}}}const v=Object.freeze({log(){},error(){}});class _{constructor(){let e="notConfigured";const t=[],r=[],o=[],n=new Map;let i=!1,s=!1,a=new p;const c=new m;let l,f,u,d=v;const x=new $,_=new N,I=w,R=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){d.log(`Container.freeze: skipped (${String(e)}).`)}return e},j=function(e){let r=e;for(const e of t)r=e(r);return r},A=function(e){let t=e;for(const e of r)t=e(t);return t},z=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},O=function(e){s&&d.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){z(),O("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){z(),O("addPostprocess()."),r.push(e)},this.addNamespaceRoot=function(e,t,r){z(),O(`addNamespaceRoot('${e}').`),o.push({prefix:e,target:t,defaultExt:r})},this.enableTestMode=function(){z(),O("enableTestMode()."),i=!0},this.enableLogging=function(){z(),s||(s=!0,d=new b,"function"==typeof a.setLogger&&a.setLogger(d),d.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(z(),O(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const r=a.parse(e);n.set(I(r),t)},this.get=async function(t){if("failed"===e)throw d.error(`Container.get: rejected in failed state cdc='${t}'.`),new Error("Container is in failed state.");try{return function(){if("notConfigured"!==e)return;d.log("Container.transition: notConfigured -> operational."),e="operational";const t=c.create({namespaces:o});"function"==typeof a.setLogger&&a.setLogger(d),l=new g({config:t,logger:d}),f=new y({parser:a,resolver:l,logger:d}),u=new E(d)}(),d.log(`Container.state: '${e}'.`),await async function(e,t){const{parser:r,resolver:o,graphResolver:n,lifecycle:i,instantiator:s,wrapperExecutor:a,logger:c,testMode:l,mockRegistry:p,freeze:f,applyPreprocess:u,applyPostprocess:d}=e;if(!o||!n||!i)throw new Error("Container infrastructure is not initialized.");const m=w,g=w;let y="start";try{c.log(`Container.get: cdc='${t}'.`),y="parse",c.log("Container.pipeline: parse:entry.");const e=r.parse(t);c.log(`Container.pipeline: parse:exit '${e.platform}::${e.moduleName}'.`),y="preprocess",c.log("Container.pipeline: preprocess:entry.");const o=u(e);if(c.log(`Container.pipeline: preprocess:exit '${o.platform}::${o.moduleName}'.`),!0===l){y="mock",c.log("Container.pipeline: mock-lookup:entry.");const e=g(o);if(p.has(e)){c.log(`Container.pipeline: mock-lookup:hit '${e}'.`),y="freeze",c.log("Container.pipeline: freeze:entry.");const t=f(p.get(e));return c.log("Container.pipeline: freeze:exit."),c.log("Container.pipeline: return:success."),C(t)}c.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else c.log("Container.pipeline: mock-lookup:disabled.");y="resolve",c.log("Container.pipeline: resolve:entry.");const w=await n.resolve(o);c.log(`Container.pipeline: resolve:exit nodes=${w.size}.`);const $=new Map,E=function(e){if($.has(e))return $.get(e);if(!w.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=w.get(e);y="lifecycle",c.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const o=i.apply(t.depId,function(){y="instantiate",c.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},o=h(t.namespace,t.depId);for(const[t,n]of Object.entries(o)){const o=r.parse(n);e[t]=E(m(o))}const n=s.instantiate(t.depId,t.namespace,e);c.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),y="postprocess",c.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=d(n);c.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const l=a.execute(t.depId,i,t.namespace);y="freeze",c.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const p=f(l);return c.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),p});return c.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),$.set(e,o),o},N=E(m(o));return c.log("Container.pipeline: return:success."),C(N)}catch(e){throw c.error(`Container.pipeline: failed at stage='${y}'.`,e),e}}({parser:a,resolver:l,graphResolver:f,lifecycle:u,instantiator:x,wrapperExecutor:_,logger:d,testMode:i,mockRegistry:n,freeze:R,applyPreprocess:j,applyPostprocess:A},t)}catch(t){throw d.error("Container.transition: operational -> failed.",t),e="failed",t}}}}export{_ as default};
1
+ var e=Object.freeze({AS_IS:"A",FACTORY:"F"});var t=Object.freeze({SINGLETON:"S",TRANSIENT:"T"});var r=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const o=r.TEQ,n=e.AS_IS,i=new Set(Object.values(r)),s=new Set(Object.values(e)),c=new Set(Object.values(t));let a=class{moduleName;platform;exportName;composition;life;wrappers;origin},l=class{create(e){const t=e&&"object"==typeof e?e:{},r=new a;r.moduleName="string"==typeof t.moduleName?t.moduleName:"";const l="string"==typeof t.platform?t.platform:void 0;r.platform=l&&i.has(l)?l:o;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),r.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;r.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return r.life=u&&c.has(u)?u:null,r.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],r.origin="string"==typeof t.origin?t.origin:"",Object.freeze(r.wrappers),Object.freeze(r)}};class p{constructor(){const o=new l;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("Dependency Specifier must be a string.");if(0===i.length)throw new Error("Dependency Specifier must be non-empty.");if(!/^[\x00-\x7F]+$/.test(i))throw new Error("Dependency Specifier must be ASCII.");const s=i,c=function(e){let t=r.TEQ;if(e.startsWith("node:"))return t=r.NODE,{platform:t,source:e.slice(5)};if(e.startsWith("npm:"))return t=r.NPM,{platform:t,source:e.slice(4)};if(e.startsWith("teq:"))throw new Error("Explicit teq: prefix is forbidden.");return{platform:t,source:e}}(i),a=c.platform,l=c.source;if(0===l.length)throw new Error("moduleName must be non-empty.");const p=function(e,o){let n=null,i=!1,s=[],c=e;const a=c.match(/(\${1,3})(?:_[a-z][0-9A-Za-z]*)*$/);if(a){const e=a[1],r=a[0].slice(e.length);if(i=!0,"$"===e)n=t.SINGLETON;else if("$$"===e)n=t.TRANSIENT;else{if("$$$"!==e)throw new Error("Lifecycle marker is invalid.");n=null}return c=c.slice(0,a.index),r.length>0&&(s=r.slice(1).split("_")),{core:c,life:n,lifecycleDeclared:i,wrappers:s}}if(e.includes("$"))throw new Error("Invalid lifecycle encoding.");if(o!==r.NODE&&/(?:^|[^_])_[a-z][0-9A-Za-z]*$/.test(e))throw new Error("Wrapper without lifecycle is forbidden.");return{core:c,life:n,lifecycleDeclared:i,wrappers:s}}(l,a),f=function(e){const t=e.indexOf("__"),r=e.lastIndexOf("__");if(-1!==t&&t!==r)throw new Error("Export delimiter must appear at most once.");if(e.startsWith("__")||e.endsWith("__"))throw new Error("Malformed export segment.");let o=e,n=null;if(-1!==t){if(o=e.slice(0,t),n=e.slice(t+2),!n)throw new Error("Export must be non-empty.");if(n.includes("_"))throw new Error("Export must not contain _.");if(n.includes("$"))throw new Error("Export must not contain $.")}return{moduleName:o,exportName:n}}(p.core);!function(e,t){if(!e)throw new Error("moduleName must be non-empty.");if(e.startsWith("_")||e.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(e.includes("__"))throw new Error("moduleName must not contain __.");if(e.includes("$"))throw new Error("moduleName must not contain $.");if(t!==r.NPM){if(t===r.NODE){if(!/^[A-Za-z_][$0-9A-Za-z_/-]*$/.test(e))throw new Error("node moduleName must satisfy the built-in specifier form.")}else if(!/^[A-Za-z_][$0-9A-Za-z_]*$/.test(e))throw new Error("moduleName must satisfy the canonical identifier form.")}else if(!/^[@A-Za-z_][$0-9A-Za-z_./-]*$/.test(e))throw new Error("npm moduleName must satisfy the package specifier form.")}(f.moduleName,a);let u=e.AS_IS,d=f.exportName;p.lifecycleDeclared&&(null===d&&(d="default"),u=e.FACTORY);const m=o.create({moduleName:f.moduleName,platform:a,exportName:d,composition:u,life:p.life,wrappers:p.wrappers,origin:s});return n&&n.log(`Parser.parse: produced='${m.platform}::${m.moduleName}'.`),m},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},r=new f;return r.prefix="string"==typeof t.prefix?t.prefix:void 0,r.target="string"==typeof t.target?t.target:void 0,r.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(r)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const r=t&&"object"==typeof t?t:{},o=new d,n=Array.isArray(r.namespaces)?r.namespaces:[];return o.namespaces=n.map(t=>e.create(t)),o.nodeModulesRoot="string"==typeof r.nodeModulesRoot?r.nodeModulesRoot:void 0,Object.freeze(o.namespaces),Object.freeze(o)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:r=null}){const o=new Map,n=e;let i;const s=t,c=r,a=function(e,t){if("node"===e){const e=`node:${t}`;return c&&c.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return c&&c.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const r=function(e){let t=null,r=-1;const o=i.namespaces;for(const n of o){const o=e.startsWith(n.prefix);c&&c.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(o)} module='${e}'.`),o&&n.prefix.length>r&&(t=n,r=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),o=t.slice(r.prefix.length).split("_").join("/"),n=(s=o,(a=r.defaultExt)?s.endsWith(a)?s:`${s}${a}`:s);var s,a;const l=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(r.target,n);return c&&c.log(`Resolver.specifier: module='${t}' -> '${l}'.`),l};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 r=e.platform,l=e.moduleName,p=`${r}::${l}`;if(o.has(p))return c&&c.log(`Resolver.cache: hit key='${p}'.`),o.get(p);c&&c.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=a(r,l);return c&&c.log(`Resolver.import: '${e}'.`),s(e)})();o.set(p,f);try{return await f}catch(e){throw o.delete(p),c&&c.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}function w(e){const t=null===e.exportName?"":e.exportName,r=null===e.life?"":e.life,o=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,r,o].join("::")}class h{constructor({canonicalize:e,parser:t,findMock:r=()=>({found:!1,value:void 0}),resolver:o,logger:n=null}){e??=t.parse.bind(t);const i=n,s=w,c=async function(t,n,a,l){const p=s(t);if(a.has(p)){const e=[...l,p].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const f=s(t);if(n.has(f))return;const u=r(t);if(u.found)n.set(f,{depId:t,namespace:null,dependencies:new Map,mock:u});else{a.add(p),l.push(p);try{const r=await o.resolve(t);i&&i.log(`GraphResolver.walk: resolved '${f}'.`);const p=new Map;n.set(f,{depId:t,namespace:r,dependencies:p,mock:u});const d=function(e,t){const r=Reflect.get(e,"__deps__");if(void 0===r)return{};if(null===r||"object"!=typeof r||Array.isArray(r))throw new Error("__deps__ must be a plain object.");const o=null===t.exportName?"default":t.exportName,n=Reflect.get(r,o);if(null!=n&&"object"==typeof n&&!Array.isArray(n)){if(!Object.values(n).every(e=>"string"==typeof e))throw new Error("__deps__ export entries must map dependency names to Dependency Specifier strings.");return n}if("default"===o){const e=Object.values(r);if(e.every(e=>"string"==typeof e))return r;if(e.every(e=>null!==e&&"object"==typeof e&&!Array.isArray(e)))return{};throw new Error("__deps__ must be either flat or export-scoped.")}return{}}(r,t);for(const[t,r]of Object.entries(d)){const o=e(r);p.set(t,s(o)),i&&i.log(`GraphResolver.walk: edge '${f}' -> '${o.platform}::${o.moduleName}'.`),await c(o,n,a,l)}}finally{l.pop(),a.delete(p)}}};this.resolve=async function(e){const t=new Map,r=new Set;return await c(e,t,r,[]),t}}}class y{constructor(){this.instantiate=function(t,r,o){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,r);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(o)}else{t=e(o)}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(r=null){const o=new Map,n=r,i=w;this.apply=function(r,s){if(r.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${r.composition}' cache=skip.`),s();if(r.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),s();if(r.life===t.SINGLETON){const e=i(r);if(o.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),o.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=s();return o.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),s()}}}class E{constructor(){const e=function(e){return"function"==typeof e};this.execute=function(t,r,o){let n=r;const i=t.wrappers;for(const t of i){if(!(t in o))throw new Error(`Wrapper '${t}' is not found in module namespace.`);const r=o[t];if(!e(r))throw new Error(`Wrapper '${t}' must be callable.`);if(n=r(n),n instanceof Promise)throw new Error(`Wrapper '${t}' must return synchronously (non-Promise).`)}return n}}}const N=new WeakMap;function x(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;const r=e;if(N.has(r))return N.get(r);try{return Reflect.get(r,"then"),e}catch{const e=new Proxy(r,{get(e,t,r){if("then"!==t)return Reflect.get(e,t,r)}});return N.set(r,e),e}}class v{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,r){console.error(`${t} ${e}`),r instanceof Error?console.error(r.stack??r.message):void 0!==r&&console.error(r)}}}const b=Object.freeze({log(){},error(){}});class _{constructor(){let e="notConfigured";const t=[],r=[],o=[],n=new Map;let i=!1,s=!1,c=new p;const a=new m;let l,f,u,d=b;const N=new y,_=new E,C=w;let z=function(e){if(null==e)return e;const t=typeof e;return"object"!==t&&"function"!==t||"[object Module]"===Object.prototype.toString.call(e)||Object.isFrozen(e)?e:Object.freeze(e)};const I=function(e){return function(e){let r=e;for(const e of t)r=e(r);return r}(c.parse(e))},k=function(e){const t=C(e);return{found:!0===i&&n.has(t),value:n.get(t)}},R=function(e,t){let o=e;const n=Object.freeze({depId:t});for(const e of r)if(o=e(o,n),o instanceof Promise)throw new Error("Postprocess callback must return synchronously (non-Promise).");return o},j=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},A=function(e){s&&d.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){j(),A("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){j(),A("addPostprocess()."),r.push(e)},this.setHardener=function(e){j(),A("setHardener()."),z=e},this.addNamespaceRoot=function(e,t,r){j(),A(`addNamespaceRoot('${e}').`),o.push({prefix:e,target:t,defaultExt:r})},this.enableTestMode=function(){j(),A("enableTestMode()."),i=!0},this.enableLogging=function(){j(),s||(s=!0,d=new v,"function"==typeof c.setLogger&&c.setLogger(d),d.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(j(),A(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const r=I(e);n.set(C(r),t)},this.get=async function(t){if("failed"===e)throw d.error(`Container.get: rejected in failed state specifier='${t}'.`),new Error("Container is in failed state.");try{return function(){if("notConfigured"!==e)return;d.log("Container.transition: notConfigured -> operational."),e="operational";const t=a.create({namespaces:o});"function"==typeof c.setLogger&&c.setLogger(d),l=new g({config:t,logger:d}),f=new h({canonicalize:I,findMock:k,resolver:l,logger:d}),u=new $(d)}(),d.log(`Container.state: '${e}'.`),await async function(e,t){const{resolver:r,graphResolver:o,lifecycle:n,instantiator:i,wrapperExecutor:s,logger:c,testMode:a,mockRegistry:l,freeze:p,canonicalize:f,applyPostprocess:u}=e;if(!r||!o||!n)throw new Error("Container infrastructure is not initialized.");const d=w,m=w;let g="start";try{c.log(`Container.get: specifier='${t}'.`),g="parse",c.log("Container.pipeline: parse:entry.");const e=f(t),r=e;if(c.log(`Container.pipeline: parse:exit '${r.platform}::${r.moduleName}'.`),g="preprocess",c.log("Container.pipeline: preprocess:entry."),c.log(`Container.pipeline: preprocess:exit '${e.platform}::${e.moduleName}'.`),!0===a){g="mock",c.log("Container.pipeline: mock-lookup:entry.");const t=m(e);if(l.has(t)){c.log(`Container.pipeline: mock-lookup:hit '${t}'.`),g="freeze",c.log("Container.pipeline: freeze:entry.");const e=p(l.get(t));return c.log("Container.pipeline: freeze:exit."),c.log("Container.pipeline: return:success."),x(e)}c.log(`Container.pipeline: mock-lookup:miss '${t}'.`)}else c.log("Container.pipeline: mock-lookup:disabled.");g="resolve",c.log("Container.pipeline: resolve:entry.");const w=await o.resolve(e);c.log(`Container.pipeline: resolve:exit nodes=${w.size}.`);const h=new Map,y=function(e){if(h.has(e))return h.get(e);if(!w.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=w.get(e);if(t.mock?.found)return g="freeze",p(t.mock.value);g="lifecycle",c.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=n.apply(t.depId,function(){g="instantiate",c.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={};for(const[r,o]of t.dependencies??[])e[r]=y(o);const r=i.instantiate(t.depId,t.namespace,e);c.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),g="postprocess",c.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const o=u(r,t.depId);c.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const n=s.execute(t.depId,o,t.namespace);g="freeze",c.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const a=p(n);return c.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),a});return c.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),h.set(e,r),r},$=y(d(e));return c.log("Container.pipeline: return:success."),x($)}catch(e){throw c.error(`Container.pipeline: failed at stage='${g}'.`,e),e}}({resolver:l,graphResolver:f,lifecycle:u,instantiator:N,wrapperExecutor:_,logger:d,testMode:i,mockRegistry:n,freeze:z,canonicalize:I,applyPostprocess:R},t)}catch(t){throw d.error("Container.transition: operational -> failed.",t),e="failed",t}}}}export{_ 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 r=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const o=r.TEQ,n=e.AS_IS,i=new Set(Object.values(r)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let c=class{moduleName;platform;exportName;composition;life;wrappers;origin},l=class{create(e){const t=e&&"object"==typeof e?e:{},r=new c;r.moduleName="string"==typeof t.moduleName?t.moduleName:"";const l="string"==typeof t.platform?t.platform:void 0;r.platform=l&&i.has(l)?l:o;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),r.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;r.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return r.life=u&&a.has(u)?u:null,r.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],r.origin="string"==typeof t.origin?t.origin:"",Object.freeze(r.wrappers),Object.freeze(r)}};class p{constructor(){const o=new l;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(!/^[\x00-\x7F]+$/.test(i))throw new Error("CDC must be ASCII.");const s=i,a=function(e){let t=r.TEQ;if(e.startsWith("node:"))return t=r.NODE,{platform:t,source:e.slice(5)};if(e.startsWith("npm:"))return t=r.NPM,{platform:t,source:e.slice(4)};if(e.startsWith("teq:"))throw new Error("Explicit teq: prefix is forbidden.");return{platform:t,source:e}}(i),c=a.platform,l=a.source;if(0===l.length)throw new Error("moduleName must be non-empty.");const p=function(e,o){let n=null,i=!1,s=[],a=e;const c=a.match(/(\${1,3})(?:_[a-z][0-9A-Za-z]*)*$/);if(c){const e=c[1],r=c[0].slice(e.length);if(i=!0,"$"===e)n=t.SINGLETON;else if("$$"===e)n=t.TRANSIENT;else{if("$$$"!==e)throw new Error("Lifecycle marker is invalid.");n=null}return a=a.slice(0,c.index),r.length>0&&(s=r.slice(1).split("_")),{core:a,life:n,lifecycleDeclared:i,wrappers:s}}if(e.includes("$"))throw new Error("Invalid lifecycle encoding.");if(o!==r.NODE&&/(?:^|[^_])_[a-z][0-9A-Za-z]*$/.test(e))throw new Error("Wrapper without lifecycle is forbidden.");return{core:a,life:n,lifecycleDeclared:i,wrappers:s}}(l,c),f=function(e){const t=e.indexOf("__"),r=e.lastIndexOf("__");if(-1!==t&&t!==r)throw new Error("Export delimiter must appear at most once.");if(e.startsWith("__")||e.endsWith("__"))throw new Error("Malformed export segment.");let o=e,n=null;if(-1!==t){if(o=e.slice(0,t),n=e.slice(t+2),!n)throw new Error("Export must be non-empty.");if(n.includes("_"))throw new Error("Export must not contain _.");if(n.includes("$"))throw new Error("Export must not contain $.")}return{moduleName:o,exportName:n}}(p.core);!function(e,t){if(!e)throw new Error("moduleName must be non-empty.");if(e.startsWith("_")||e.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(e.includes("__"))throw new Error("moduleName must not contain __.");if(e.includes("$"))throw new Error("moduleName must not contain $.");if(t!==r.NPM){if(t===r.NODE){if(!/^[A-Za-z_][$0-9A-Za-z_/-]*$/.test(e))throw new Error("node moduleName must satisfy the built-in specifier form.")}else if(!/^[A-Za-z_][$0-9A-Za-z_]*$/.test(e))throw new Error("moduleName must satisfy the canonical identifier form.")}else if(!/^[@A-Za-z_][$0-9A-Za-z_./-]*$/.test(e))throw new Error("npm moduleName must satisfy the package specifier form.")}(f.moduleName,c);let u=e.AS_IS,d=f.exportName;p.lifecycleDeclared&&(null===d&&(d="default"),u=e.FACTORY);const m=o.create({moduleName:f.moduleName,platform:c,exportName:d,composition:u,life:p.life,wrappers:p.wrappers,origin:s});return n&&n.log(`Parser.parse: produced='${m.platform}::${m.moduleName}'.`),m},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},r=new f;return r.prefix="string"==typeof t.prefix?t.prefix:void 0,r.target="string"==typeof t.target?t.target:void 0,r.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(r)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const r=t&&"object"==typeof t?t:{},o=new d,n=Array.isArray(r.namespaces)?r.namespaces:[];return o.namespaces=n.map(t=>e.create(t)),o.nodeModulesRoot="string"==typeof r.nodeModulesRoot?r.nodeModulesRoot:void 0,Object.freeze(o.namespaces),Object.freeze(o)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:r=null}){const o=new Map,n=e;let i;const s=t,a=r,c=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 r=function(e){let t=null,r=-1;const o=i.namespaces;for(const n of o){const o=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(o)} module='${e}'.`),o&&n.prefix.length>r&&(t=n,r=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),o=t.slice(r.prefix.length).split("_").join("/"),n=(s=o,(c=r.defaultExt)?s.endsWith(c)?s:`${s}${c}`:s);var s,c;const l=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(r.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${l}'.`),l};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 r=e.platform,l=e.moduleName,p=`${r}::${l}`;if(o.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),o.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=c(r,l);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();o.set(p,f);try{return await f}catch(e){throw o.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}function w(e){const t=null===e.exportName?"":e.exportName,r=null===e.life?"":e.life,o=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,r,o].join("::")}function h(e,t){const r=Reflect.get(e,"__deps__");if(void 0===r)return{};if(null===r||"object"!=typeof r||Array.isArray(r))throw new Error("__deps__ must be a plain object.");const o=null===t.exportName?"default":t.exportName,n=Reflect.get(r,o);if(null!=n&&"object"==typeof n&&!Array.isArray(n)){if(!Object.values(n).every(e=>"string"==typeof e))throw new Error("__deps__ export entries must map dependency names to CDC strings.");return n}if("default"===o){const e=Object.values(r);if(e.every(e=>"string"==typeof e))return r;if(e.every(e=>null!==e&&"object"==typeof e&&!Array.isArray(e)))return{};throw new Error("__deps__ must be either flat or export-scoped.")}return{}}class y{constructor({parser:e,resolver:t,logger:r=null}){const o=r,n=w,i=async function(r,s,a,c){const l=n(r);if(a.has(l)){const e=[...c,l].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const p=n(r);if(!s.has(p)){a.add(l),c.push(l);try{const n=await t.resolve(r);o&&o.log(`GraphResolver.walk: resolved '${p}'.`),s.set(p,{depId:r,namespace:n});const l=h(n,r);for(const t of Object.values(l)){const r=e.parse(t);o&&o.log(`GraphResolver.walk: edge '${p}' -> '${r.platform}::${r.moduleName}'.`),await i(r,s,a,c)}}finally{c.pop(),a.delete(l)}}};this.resolve=async function(e){const t=new Map,r=new Set;return await i(e,t,r,[]),t}}}class ${constructor(){this.instantiate=function(t,r,o){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,r);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(o)}else{t=e(o)}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 x{constructor(r=null){const o=new Map,n=r,i=w;this.apply=function(r,s){if(r.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${r.composition}' cache=skip.`),s();if(r.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),s();if(r.life===t.SINGLETON){const e=i(r);if(o.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),o.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=s();return o.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),s()}}}class E{constructor(){const e=function(e){return"function"==typeof e};this.execute=function(t,r,o){let n=r;const i=t.wrappers;for(const t of i){if(!(t in o))throw new Error(`Wrapper '${t}' is not found in module namespace.`);const r=o[t];if(!e(r))throw new Error(`Wrapper '${t}' must be callable.`);if(n=r(n),n instanceof Promise)throw new Error(`Wrapper '${t}' must return synchronously (non-Promise).`)}return n}}}const N=new WeakMap;function b(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;const r=e;if(N.has(r))return N.get(r);try{return Reflect.get(r,"then"),e}catch{const e=new Proxy(r,{get(e,t,r){if("then"!==t)return Reflect.get(e,t,r)}});return N.set(r,e),e}}class C{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,r){console.error(`${t} ${e}`),r instanceof Error?console.error(r.stack??r.message):void 0!==r&&console.error(r)}}}const v=Object.freeze({log(){},error(){}});return class{constructor(){let e="notConfigured";const t=[],r=[],o=[],n=new Map;let i=!1,s=!1,a=new p;const c=new m;let l,f,u,d=v;const N=new $,_=new E,j=w,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){d.log(`Container.freeze: skipped (${String(e)}).`)}return e},R=function(e){let r=e;for(const e of t)r=e(r);return r},A=function(e){let t=e;for(const e of r)t=e(t);return t},z=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},O=function(e){s&&d.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){z(),O("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){z(),O("addPostprocess()."),r.push(e)},this.addNamespaceRoot=function(e,t,r){z(),O(`addNamespaceRoot('${e}').`),o.push({prefix:e,target:t,defaultExt:r})},this.enableTestMode=function(){z(),O("enableTestMode()."),i=!0},this.enableLogging=function(){z(),s||(s=!0,d=new C,"function"==typeof a.setLogger&&a.setLogger(d),d.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(z(),O(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const r=a.parse(e);n.set(j(r),t)},this.get=async function(t){if("failed"===e)throw d.error(`Container.get: rejected in failed state cdc='${t}'.`),new Error("Container is in failed state.");try{return function(){if("notConfigured"!==e)return;d.log("Container.transition: notConfigured -> operational."),e="operational";const t=c.create({namespaces:o});"function"==typeof a.setLogger&&a.setLogger(d),l=new g({config:t,logger:d}),f=new y({parser:a,resolver:l,logger:d}),u=new x(d)}(),d.log(`Container.state: '${e}'.`),await async function(e,t){const{parser:r,resolver:o,graphResolver:n,lifecycle:i,instantiator:s,wrapperExecutor:a,logger:c,testMode:l,mockRegistry:p,freeze:f,applyPreprocess:u,applyPostprocess:d}=e;if(!o||!n||!i)throw new Error("Container infrastructure is not initialized.");const m=w,g=w;let y="start";try{c.log(`Container.get: cdc='${t}'.`),y="parse",c.log("Container.pipeline: parse:entry.");const e=r.parse(t);c.log(`Container.pipeline: parse:exit '${e.platform}::${e.moduleName}'.`),y="preprocess",c.log("Container.pipeline: preprocess:entry.");const o=u(e);if(c.log(`Container.pipeline: preprocess:exit '${o.platform}::${o.moduleName}'.`),!0===l){y="mock",c.log("Container.pipeline: mock-lookup:entry.");const e=g(o);if(p.has(e)){c.log(`Container.pipeline: mock-lookup:hit '${e}'.`),y="freeze",c.log("Container.pipeline: freeze:entry.");const t=f(p.get(e));return c.log("Container.pipeline: freeze:exit."),c.log("Container.pipeline: return:success."),b(t)}c.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else c.log("Container.pipeline: mock-lookup:disabled.");y="resolve",c.log("Container.pipeline: resolve:entry.");const w=await n.resolve(o);c.log(`Container.pipeline: resolve:exit nodes=${w.size}.`);const $=new Map,x=function(e){if($.has(e))return $.get(e);if(!w.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=w.get(e);y="lifecycle",c.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const o=i.apply(t.depId,function(){y="instantiate",c.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},o=h(t.namespace,t.depId);for(const[t,n]of Object.entries(o)){const o=r.parse(n);e[t]=x(m(o))}const n=s.instantiate(t.depId,t.namespace,e);c.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),y="postprocess",c.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=d(n);c.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const l=a.execute(t.depId,i,t.namespace);y="freeze",c.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const p=f(l);return c.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),p});return c.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),$.set(e,o),o},E=x(m(o));return c.log("Container.pipeline: return:success."),b(E)}catch(e){throw c.error(`Container.pipeline: failed at stage='${y}'.`,e),e}}({parser:a,resolver:l,graphResolver:f,lifecycle:u,instantiator:N,wrapperExecutor:_,logger:d,testMode:i,mockRegistry:n,freeze:I,applyPreprocess:R,applyPostprocess:A},t)}catch(t){throw d.error("Container.transition: operational -> failed.",t),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)),c=new Set(Object.values(t));let a=class{moduleName;platform;exportName;composition;life;wrappers;origin},l=class{create(e){const t=e&&"object"==typeof e?e:{},o=new a;o.moduleName="string"==typeof t.moduleName?t.moduleName:"";const l="string"==typeof t.platform?t.platform:void 0;o.platform=l&&i.has(l)?l: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&&c.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 l;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("Dependency Specifier must be a string.");if(0===i.length)throw new Error("Dependency Specifier must be non-empty.");if(!/^[\x00-\x7F]+$/.test(i))throw new Error("Dependency Specifier must be ASCII.");const s=i,c=function(e){let t=o.TEQ;if(e.startsWith("node:"))return t=o.NODE,{platform:t,source:e.slice(5)};if(e.startsWith("npm:"))return t=o.NPM,{platform:t,source:e.slice(4)};if(e.startsWith("teq:"))throw new Error("Explicit teq: prefix is forbidden.");return{platform:t,source:e}}(i),a=c.platform,l=c.source;if(0===l.length)throw new Error("moduleName must be non-empty.");const p=function(e,r){let n=null,i=!1,s=[],c=e;const a=c.match(/(\${1,3})(?:_[a-z][0-9A-Za-z]*)*$/);if(a){const e=a[1],o=a[0].slice(e.length);if(i=!0,"$"===e)n=t.SINGLETON;else if("$$"===e)n=t.TRANSIENT;else{if("$$$"!==e)throw new Error("Lifecycle marker is invalid.");n=null}return c=c.slice(0,a.index),o.length>0&&(s=o.slice(1).split("_")),{core:c,life:n,lifecycleDeclared:i,wrappers:s}}if(e.includes("$"))throw new Error("Invalid lifecycle encoding.");if(r!==o.NODE&&/(?:^|[^_])_[a-z][0-9A-Za-z]*$/.test(e))throw new Error("Wrapper without lifecycle is forbidden.");return{core:c,life:n,lifecycleDeclared:i,wrappers:s}}(l,a),f=function(e){const t=e.indexOf("__"),o=e.lastIndexOf("__");if(-1!==t&&t!==o)throw new Error("Export delimiter must appear at most once.");if(e.startsWith("__")||e.endsWith("__"))throw new Error("Malformed export segment.");let r=e,n=null;if(-1!==t){if(r=e.slice(0,t),n=e.slice(t+2),!n)throw new Error("Export must be non-empty.");if(n.includes("_"))throw new Error("Export must not contain _.");if(n.includes("$"))throw new Error("Export must not contain $.")}return{moduleName:r,exportName:n}}(p.core);!function(e,t){if(!e)throw new Error("moduleName must be non-empty.");if(e.startsWith("_")||e.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(e.includes("__"))throw new Error("moduleName must not contain __.");if(e.includes("$"))throw new Error("moduleName must not contain $.");if(t!==o.NPM){if(t===o.NODE){if(!/^[A-Za-z_][$0-9A-Za-z_/-]*$/.test(e))throw new Error("node moduleName must satisfy the built-in specifier form.")}else if(!/^[A-Za-z_][$0-9A-Za-z_]*$/.test(e))throw new Error("moduleName must satisfy the canonical identifier form.")}else if(!/^[@A-Za-z_][$0-9A-Za-z_./-]*$/.test(e))throw new Error("npm moduleName must satisfy the package specifier form.")}(f.moduleName,a);let u=e.AS_IS,d=f.exportName;p.lifecycleDeclared&&(null===d&&(d="default"),u=e.FACTORY);const m=r.create({moduleName:f.moduleName,platform:a,exportName:d,composition:u,life:p.life,wrappers:p.wrappers,origin:s});return n&&n.log(`Parser.parse: produced='${m.platform}::${m.moduleName}'.`),m},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,c=o,a=function(e,t){if("node"===e){const e=`node:${t}`;return c&&c.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return c&&c.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);c&&c.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,(a=o.defaultExt)?s.endsWith(a)?s:`${s}${a}`:s);var s,a;const l=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return c&&c.log(`Resolver.specifier: module='${t}' -> '${l}'.`),l};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,l=e.moduleName,p=`${o}::${l}`;if(r.has(p))return c&&c.log(`Resolver.cache: hit key='${p}'.`),r.get(p);c&&c.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=a(o,l);return c&&c.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),c&&c.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}function w(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("::")}class h{constructor({canonicalize:e,parser:t,findMock:o=()=>({found:!1,value:void 0}),resolver:r,logger:n=null}){e??=t.parse.bind(t);const i=n,s=w,c=async function(t,n,a,l){const p=s(t);if(a.has(p)){const e=[...l,p].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const f=s(t);if(n.has(f))return;const u=o(t);if(u.found)n.set(f,{depId:t,namespace:null,dependencies:new Map,mock:u});else{a.add(p),l.push(p);try{const o=await r.resolve(t);i&&i.log(`GraphResolver.walk: resolved '${f}'.`);const p=new Map;n.set(f,{depId:t,namespace:o,dependencies:p,mock:u});const d=function(e,t){const o=Reflect.get(e,"__deps__");if(void 0===o)return{};if(null===o||"object"!=typeof o||Array.isArray(o))throw new Error("__deps__ must be a plain object.");const r=null===t.exportName?"default":t.exportName,n=Reflect.get(o,r);if(null!=n&&"object"==typeof n&&!Array.isArray(n)){if(!Object.values(n).every(e=>"string"==typeof e))throw new Error("__deps__ export entries must map dependency names to Dependency Specifier strings.");return n}if("default"===r){const e=Object.values(o);if(e.every(e=>"string"==typeof e))return o;if(e.every(e=>null!==e&&"object"==typeof e&&!Array.isArray(e)))return{};throw new Error("__deps__ must be either flat or export-scoped.")}return{}}(o,t);for(const[t,o]of Object.entries(d)){const r=e(o);p.set(t,s(r)),i&&i.log(`GraphResolver.walk: edge '${f}' -> '${r.platform}::${r.moduleName}'.`),await c(r,n,a,l)}}finally{l.pop(),a.delete(p)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await c(e,t,o,[]),t}}}class y{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,i=w;this.apply=function(o,s){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),s();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),s();if(o.life===t.SINGLETON){const e=i(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=s();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."),s()}}}class E{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}}}const x=new WeakMap;function N(e){if(null==e)return e;const t=typeof e;if("object"!==t&&"function"!==t)return e;const o=e;if(x.has(o))return x.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 x.set(o,e),e}}class b{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 v=Object.freeze({log(){},error(){}});return class{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map;let i=!1,s=!1,c=new p;const a=new m;let l,f,u,d=v;const x=new y,_=new E,C=w;let z=function(e){if(null==e)return e;const t=typeof e;return"object"!==t&&"function"!==t||"[object Module]"===Object.prototype.toString.call(e)||Object.isFrozen(e)?e:Object.freeze(e)};const I=function(e){return function(e){let o=e;for(const e of t)o=e(o);return o}(c.parse(e))},j=function(e){const t=C(e);return{found:!0===i&&n.has(t),value:n.get(t)}},k=function(e,t){let r=e;const n=Object.freeze({depId:t});for(const e of o)if(r=e(r,n),r instanceof Promise)throw new Error("Postprocess callback must return synchronously (non-Promise).");return r},R=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},A=function(e){s&&d.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){R(),A("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){R(),A("addPostprocess()."),o.push(e)},this.setHardener=function(e){R(),A("setHardener()."),z=e},this.addNamespaceRoot=function(e,t,o){R(),A(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){R(),A("enableTestMode()."),i=!0},this.enableLogging=function(){R(),s||(s=!0,d=new b,"function"==typeof c.setLogger&&c.setLogger(d),d.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(R(),A(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const o=I(e);n.set(C(o),t)},this.get=async function(t){if("failed"===e)throw d.error(`Container.get: rejected in failed state specifier='${t}'.`),new Error("Container is in failed state.");try{return function(){if("notConfigured"!==e)return;d.log("Container.transition: notConfigured -> operational."),e="operational";const t=a.create({namespaces:r});"function"==typeof c.setLogger&&c.setLogger(d),l=new g({config:t,logger:d}),f=new h({canonicalize:I,findMock:j,resolver:l,logger:d}),u=new $(d)}(),d.log(`Container.state: '${e}'.`),await async function(e,t){const{resolver:o,graphResolver:r,lifecycle:n,instantiator:i,wrapperExecutor:s,logger:c,testMode:a,mockRegistry:l,freeze:p,canonicalize:f,applyPostprocess:u}=e;if(!o||!r||!n)throw new Error("Container infrastructure is not initialized.");const d=w,m=w;let g="start";try{c.log(`Container.get: specifier='${t}'.`),g="parse",c.log("Container.pipeline: parse:entry.");const e=f(t),o=e;if(c.log(`Container.pipeline: parse:exit '${o.platform}::${o.moduleName}'.`),g="preprocess",c.log("Container.pipeline: preprocess:entry."),c.log(`Container.pipeline: preprocess:exit '${e.platform}::${e.moduleName}'.`),!0===a){g="mock",c.log("Container.pipeline: mock-lookup:entry.");const t=m(e);if(l.has(t)){c.log(`Container.pipeline: mock-lookup:hit '${t}'.`),g="freeze",c.log("Container.pipeline: freeze:entry.");const e=p(l.get(t));return c.log("Container.pipeline: freeze:exit."),c.log("Container.pipeline: return:success."),N(e)}c.log(`Container.pipeline: mock-lookup:miss '${t}'.`)}else c.log("Container.pipeline: mock-lookup:disabled.");g="resolve",c.log("Container.pipeline: resolve:entry.");const w=await r.resolve(e);c.log(`Container.pipeline: resolve:exit nodes=${w.size}.`);const h=new Map,y=function(e){if(h.has(e))return h.get(e);if(!w.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=w.get(e);if(t.mock?.found)return g="freeze",p(t.mock.value);g="lifecycle",c.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const o=n.apply(t.depId,function(){g="instantiate",c.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={};for(const[o,r]of t.dependencies??[])e[o]=y(r);const o=i.instantiate(t.depId,t.namespace,e);c.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),g="postprocess",c.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=u(o,t.depId);c.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const n=s.execute(t.depId,r,t.namespace);g="freeze",c.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const a=p(n);return c.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),a});return c.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),h.set(e,o),o},$=y(d(e));return c.log("Container.pipeline: return:success."),N($)}catch(e){throw c.error(`Container.pipeline: failed at stage='${g}'.`,e),e}}({resolver:l,graphResolver:f,lifecycle:u,instantiator:x,wrapperExecutor:_,logger:d,testMode:i,mockRegistry:n,freeze:z,canonicalize:I,applyPostprocess:k},t)}catch(t){throw d.error("Container.transition: operational -> failed.",t),e="failed",t}}}}});
package/package.json CHANGED
@@ -1,14 +1,17 @@
1
1
  {
2
2
  "name": "@teqfw/di",
3
- "version": "2.7.0",
4
- "description": "Dependency Injection container for ES6 modules that works in both browser and Node.js apps.",
3
+ "version": "2.8.0",
4
+ "description": "Deterministic token-based runtime linker for native JavaScript ES modules.",
5
5
  "keywords": [
6
- "dependency injection",
7
- "di",
8
- "dynamic import",
9
- "es6 modules",
10
6
  "teqfw",
11
- "tequila framework"
7
+ "javascript",
8
+ "esm",
9
+ "es modules",
10
+ "runtime linking",
11
+ "dependency injection",
12
+ "module tokens",
13
+ "namespace",
14
+ "late binding"
12
15
  ],
13
16
  "homepage": "https://github.com/teqfw/di#readme",
14
17
  "bugs": {
@@ -22,6 +25,7 @@
22
25
  },
23
26
  "files": [
24
27
  "ai/",
28
+ "skills/",
25
29
  "dist/",
26
30
  "src/",
27
31
  "CHANGELOG.md",
@@ -29,8 +33,6 @@
29
33
  "README.md",
30
34
  "types.d.ts"
31
35
  ],
32
- "main": "dist/umd.js",
33
- "module": "dist/esm.js",
34
36
  "types": "types.d.ts",
35
37
  "exports": {
36
38
  ".": {
@@ -41,18 +43,23 @@
41
43
  "import": "./src/Container.mjs",
42
44
  "default": "./src/Container.mjs"
43
45
  },
44
- "./src/Container.mjs": "./src/Container.mjs",
46
+ "./node/registry/namespace": "./src/Node/Registry/Namespace.mjs",
47
+ "./node/registry/package": "./src/Node/Registry/Package.mjs",
45
48
  "./src/Config/NamespaceRegistry.mjs": "./src/Config/NamespaceRegistry.mjs"
46
49
  },
47
50
  "type": "module",
48
51
  "teqfw": {
49
- "namespaces": [
50
- {
51
- "prefix": "TeqFw_Di_",
52
- "path": "./src",
53
- "ext": ".mjs"
52
+ "fw": {
53
+ "di": {
54
+ "namespaces": [
55
+ {
56
+ "prefix": "TeqFw_Di_",
57
+ "path": "./src",
58
+ "ext": ".mjs"
59
+ }
60
+ ]
54
61
  }
55
- ]
62
+ }
56
63
  },
57
64
  "repository": {
58
65
  "type": "git",
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: teqfw-di
3
+ description: >
4
+ Use this skill when integrating, using, testing, reviewing, or modifying JavaScript
5
+ modules that use @teqfw/di runtime linking, Dependency Specifiers, namespace
6
+ mappings, lifecycle selectors, hooks, wrappers, mocks, browser ESM, or Node.js
7
+ package and namespace registries.
8
+ license: Apache-2.0
9
+ metadata:
10
+ package: "@teqfw/di"
11
+ ---
12
+
13
+ # @teqfw/di
14
+
15
+ Use this skill for consumer code that composes or depends on the installed `@teqfw/di` package. Treat the host project's instructions, architecture, and test conventions as authoritative.
16
+
17
+ ## Apply
18
+
19
+ 1. Use only public imports: `@teqfw/di`, `@teqfw/di/node/registry/namespace`, and `@teqfw/di/node/registry/package`.
20
+ 2. Never import `@teqfw/di/src/**`. Preserve `@teqfw/di/src/Config/NamespaceRegistry.mjs` only in existing migration code; new code uses `@teqfw/di/node/registry/namespace`.
21
+ 3. Configure the container before its first `get()`; retain the canonical export-scoped `__deps__` form for new or changed modules.
22
+ 4. Keep Node.js registries in a Node.js composition root. Do not import them from browser or DI-managed runtime modules.
23
+ 5. Read the references selected below before editing, then validate with the host project tests.
24
+
25
+ ## Select References
26
+
27
+ | Consumer task | Read |
28
+ | --- | --- |
29
+ | Understand package boundaries, token mapping, or compatibility | [Concepts](references/concepts.md), [Compatibility](references/compatibility.md) |
30
+ | Write or change a DI module, compose an application, use browser ESM, mocks, or package metadata | [Usage](references/usage.md), [Dependency Specifiers](references/dependency-id.md) |
31
+ | Configure a container, diagnose lock/failure behavior, or register mocks | [Container](references/container.md), [Package API](references/package-api.ts) |
32
+ | Add preprocess, postprocess, or wrappers | [Extensions](references/extensions.md), [Dependency Specifiers](references/dependency-id.md) |
33
+ | Build Node.js package-backed composition | [Usage](references/usage.md), [Concepts](references/concepts.md), [Package API](references/package-api.ts) |
34
+ | Mount or discover the installed skill | [Distribution](references/distribution.md) |
35
+
36
+ The container links stable Module Tokens through finalized namespace roots. Prefer one principal application value in `default export` and explicit source-attached `__deps__` declarations. This skill defines correct package use, not host application architecture or policy.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "TeqFW DI"
3
+ short_description: "Integrate @teqfw/di safely"
4
+ default_prompt: "Use $teqfw-di to integrate @teqfw/di in this project."
@@ -0,0 +1,35 @@
1
+ # compatibility.md
2
+
3
+ Version: 20260730
4
+
5
+ ## Purpose
6
+
7
+ This reference describes temporary public compatibility surfaces that consumers can encounter. Use canonical surfaces for all new code.
8
+
9
+ ## Deprecated Namespace Registry Import
10
+
11
+ - Deprecated import: `@teqfw/di/src/Config/NamespaceRegistry.mjs`.
12
+ - Canonical import: `@teqfw/di/node/registry/namespace`.
13
+ - Status: active only for migration of existing Node.js composition roots.
14
+ - Review date: 2027-01-28.
15
+ - Removal: only through an explicitly approved breaking release after review.
16
+
17
+ The deprecated entry re-exports the canonical registry. It does not provide different discovery, configuration, lifecycle, or browser behavior.
18
+
19
+ ## Legacy Namespace Manifest Metadata
20
+
21
+ - Deprecated field: `package.json#teqfw.namespaces`.
22
+ - Canonical field: `package.json#teqfw.fw.di.namespaces`.
23
+ - Review date: 2027-01-28.
24
+ - Removal: only through a deliberate breaking release; no date-based runtime switch exists.
25
+
26
+ Use the canonical array immediately. Legacy metadata is selected only when canonical metadata is absent; selected schemas are never merged.
27
+
28
+ ## Legacy AI Directory
29
+
30
+ - Deprecated package directory: `ai/` and `ai/AGENTS.md`.
31
+ - Canonical consumer interface: `skills/teqfw-di/SKILL.md`.
32
+ - Review date: 2026-10-30.
33
+ - Removal: only through an explicitly approved breaking release after review.
34
+
35
+ The legacy directory is a navigation pointer, not a second installed skill interface.
@@ -0,0 +1,43 @@
1
+ # concepts.md
2
+
3
+ Version: 20260727
4
+
5
+ ## Core Model
6
+
7
+ ```text
8
+ Module Token -> Module Registry -> ES Module -> Principal Application Value
9
+ ```
10
+
11
+ A Module Token is logical identity. A Module Specifier is the physical location passed to `import()`. The ES Module is the loading unit. Its `default export` is the preferred Principal Application Value; `__deps__` is metadata describing the values required to link it.
12
+
13
+ ## Late Binding
14
+
15
+ Dependencies are resolved at runtime rather than through direct static imports between application modules. This keeps modules independent of concrete implementations and moves dependency binding into the container.
16
+
17
+ ## Runtime Linker
18
+
19
+ The container acts as a runtime linker for ES modules. It interprets dependency specifiers, resolves modules, selects exports, and produces linked values for callers.
20
+
21
+ ## Dependency Specifiers And Declarations
22
+
23
+ Dependencies are declared through Dependency Specifier strings and module-level `__deps__` declarations. A specifier contains a Module Token plus optional export, lifecycle, and wrapper selectors.
24
+
25
+ The canonical `__deps__` form is hierarchical and keyed by export name.
26
+
27
+ ## Namespace Mapping
28
+
29
+ Logical module identifiers are translated into module-specifier bases through namespace roots. This keeps dependency addressing independent from concrete filesystem paths or URL locations.
30
+
31
+ A package may publish multiple namespace mappings in the canonical `teqfw.fw.di.namespaces` array. The legacy `teqfw.namespaces` array is a temporary fallback only when canonical metadata is absent; support is planned through 2027-01-28. The singular `teqfw.fw.di.namespace` form is unsupported.
32
+
33
+ ## Immutable Linked Values
34
+
35
+ Values returned by the container are frozen after linking. Consumers should treat them as stable resolved values rather than mutable construction targets.
36
+
37
+ ## Cycle Boundary
38
+
39
+ Cycles in the dependency graph managed by the container are forbidden and fail linking. Circular imports internal to third-party ESM packages remain outside the package boundary and are handled by the native loader.
40
+
41
+ ## Runtime Package Graph
42
+
43
+ PackageRegistry and NamespaceRegistry are Node.js-only composition-stage helpers. They return immutable static metadata records and namespace roots for the application root and installed transitive runtime dependencies in deterministic dependency-first postorder; ascending dependency package name is the stable tie-breaker. Applications may separately interpret provider metadata, but DI does not provide a plugin registry or load modules during discovery. Agent-authored consumers import them only from `@teqfw/di/node/registry/package` and `@teqfw/di/node/registry/namespace`, never from browser runtime code.
@@ -1,10 +1,10 @@
1
1
  # container.md
2
2
 
3
- Version: 20260606
3
+ Version: 20260728
4
4
 
5
5
  ## Role
6
6
 
7
- The container is the runtime composition root of the package. It interprets CDC identifiers, resolves them into modules, produces linked values, and returns frozen results.
7
+ The container is the Runtime Linker and composition root of the package. It parses Dependency Specifiers, extracts Module Tokens, derives Module Specifiers through the configured registry, loads ES modules, and returns Resolved Values.
8
8
 
9
9
  Application modules do not resolve dependencies themselves. They declare dependency contracts and rely on the container to perform linking.
10
10
 
@@ -30,18 +30,18 @@ After the first `get()`, builder-stage methods are no longer supported.
30
30
 
31
31
  ## Resolution Pipeline
32
32
 
33
- For each `get(cdc)` request the container applies this pipeline:
33
+ For each `get(specifier)` request the container applies this pipeline:
34
34
 
35
- 1. `Parse` — convert the CDC string into a DepId DTO.
35
+ 1. `Parse` — convert the Dependency Specifier string into a DepId DTO.
36
36
  2. `Preprocess hooks` — transform the DepId DTO through ordered `addPreprocess()` hooks.
37
37
  3. `Resolve` — map the identifier to a concrete module location.
38
38
  4. `Instantiate` — load the module and either return the selected export as-is or instantiate it according to lifecycle composition rules.
39
39
  5. `Postprocess hooks` — apply ordered `addPostprocess()` value transforms.
40
- 6. `Wrapper exports` — apply ordered wrapper exports selected by CDC suffixes.
40
+ 6. `Wrapper exports` — apply ordered wrapper exports selected by dependency specifier suffixes.
41
41
  7. `Lifecycle` — apply singleton caching or transient behavior.
42
42
  8. `Freeze` — freeze the resolved value before returning it.
43
43
 
44
- The pipeline is deterministic for a fixed configuration and input CDC.
44
+ The pipeline is deterministic for a fixed configuration and input Dependency Specifier. Preprocess and postprocess callbacks are synchronous and run in registration order; their return values are used immediately.
45
45
 
46
46
  ## State Model
47
47
 
@@ -81,3 +81,9 @@ Once in `failed` state:
81
81
  - the container does not attempt partial recovery.
82
82
 
83
83
  This fail-fast behavior prevents partially linked systems from continuing execution.
84
+
85
+ ## Package Graph Boundary
86
+
87
+ PackageRegistry and NamespaceRegistry are Node.js-only composition-stage utilities outside Container builder state. Consumers import them from `@teqfw/di/node/registry/package` and `@teqfw/di/node/registry/namespace`; browser runtime modules must not import them. They read static package metadata before namespace roots are added. The container never discovers packages or application providers while resolving dependencies.
88
+
89
+ The Rollup browser distribution build rejects any reachable `src/Node/` module.
@@ -1,15 +1,26 @@
1
1
  # dependency-id.md
2
2
 
3
- Version: 20260710
3
+ Version: 20260729
4
4
 
5
5
  ## Purpose
6
6
 
7
- Dependencies in the container are addressed using **Canonical Dependency Codes (CDC)**. A CDC is a structured identifier interpreted by the container to determine which module must be loaded, which export must be selected, and whether the resolved value is returned as-is or instantiated with lifecycle semantics.
7
+ Dependencies in the container are requested through **Dependency Specifiers**. A Dependency Specifier contains a Module Token plus optional export, lifecycle, and wrapper selectors. The token identifies the module; the selectors describe how its value is linked.
8
+
9
+ ## Contents
10
+
11
+ - [Grammar](#grammar)
12
+ - [Platform Prefixes](#platform-prefixes)
13
+ - [Module Identification](#module-identification)
14
+ - [Export Selection](#export-selection)
15
+ - [Lifecycle Markers](#lifecycle-markers)
16
+ - [Wrapper Suffixes](#wrapper-suffixes)
17
+ - [Interpretation Rules](#interpretation-rules)
18
+ - [Canonical Examples](#canonical-examples)
8
19
 
9
20
  ## Grammar
10
21
 
11
22
  ```txt
12
- CDC := [PlatformPrefix]ModuleName[__ExportName][Lifecycle][WrapperSuffixes]
23
+ dependencySpecifier := [PlatformPrefix]ModuleToken[__ExportName][Lifecycle][WrapperSuffixes]
13
24
  ```
14
25
 
15
26
  Component order is fixed.
@@ -22,7 +33,7 @@ Component order is fixed.
22
33
  ## Components
23
34
 
24
35
  - `PlatformPrefix` — optional source selector such as `node:` or `npm:`.
25
- - `ModuleName` — logical module identifier inside a namespace.
36
+ - `ModuleToken` — stable logical module identifier inside a namespace.
26
37
  - `__ExportName` — optional named export selector. With a lifecycle marker, selects the export for factory composition. Without a lifecycle marker, selects the named export for as-is resolution. Omission without a lifecycle marker means the whole-module namespace is resolved as-is.
27
38
  - `Lifecycle` — optional instantiation marker.
28
39
  - `WrapperSuffixes` — optional ordered wrapper export names appended after the lifecycle marker.
@@ -46,7 +57,7 @@ App_Service_User$
46
57
 
47
58
  ## Module Identification
48
59
 
49
- `ModuleName` identifies the provider module. Identifier segments separated by underscores correspond to path segments inside the configured namespace root.
60
+ `ModuleToken` identifies the provider module independently from its physical location. Identifier segments separated by underscores correspond to path segments inside the configured namespace root.
50
61
 
51
62
  Example:
52
63
 
@@ -60,7 +71,7 @@ may map to a module-specifier base such as:
60
71
  AppRoot/Service/User.mjs
61
72
  ```
62
73
 
63
- The base may be filesystem-backed or URL-backed depending on runtime configuration.
74
+ The base may be filesystem-backed or URL-backed depending on runtime configuration. The derived path or URL is a Module Specifier, not the Module Token.
64
75
 
65
76
  ## Export Selection
66
77
 
@@ -86,7 +97,7 @@ Supported lifecycle markers:
86
97
 
87
98
  - `$` — singleton lifecycle; create once and reuse the same instance.
88
99
  - `$$` — transient lifecycle; create a new instance each time.
89
- - `$$$` — transient alias; behaves the same as `$$` in the current implementation.
100
+ - `$$$` — direct lifecycle for factory composition; do not cache the produced value.
90
101
 
91
102
  If the lifecycle marker is omitted, the selected module export is resolved **as-is** and is not instantiated by lifecycle rules.
92
103
 
@@ -114,7 +125,7 @@ Wrapper exports are described in `extensions.md`.
114
125
 
115
126
  ## Interpretation Rules
116
127
 
117
- When the container receives a CDC it interprets it in this order:
128
+ When the container receives a Dependency Specifier it interprets it in this order:
118
129
 
119
130
  1. determine the platform prefix and module namespace;
120
131
  2. resolve the module identifier into a module location;
@@ -0,0 +1,24 @@
1
+ # distribution.md
2
+
3
+ Version: 20260730
4
+
5
+ ## Installed Location
6
+
7
+ The package publishes the version-matched skill at `node_modules/@teqfw/di/skills/teqfw-di/`. Load `SKILL.md` as its entry point. Every required reference is below that directory and describes the installed package version.
8
+
9
+ ## Host-Owned Mounting
10
+
11
+ The host project decides whether and how to make the skill discoverable. Installation performs no `postinstall` mutation, creates no links, and does not modify host agent configuration.
12
+
13
+ A host using an `.agents/skills/` catalog can mount the installed skill explicitly:
14
+
15
+ ```sh
16
+ mkdir -p .agents/skills
17
+ ln -s ../../node_modules/@teqfw/di/skills/teqfw-di .agents/skills/teqfw-di
18
+ ```
19
+
20
+ Preserve host-project instructions and cognitive context as the authority for application intent and architecture.
21
+
22
+ ## Legacy Navigation
23
+
24
+ Treat `ai/AGENTS.md`, if present, only as a temporary pointer to this canonical skill. Do not mount it as a second skill interface. Read [Compatibility](compatibility.md) for its review date and removal condition.