@teqfw/di 2.6.2 → 2.7.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 +8 -0
- package/ai/dependency-id.md +10 -4
- package/ai/package-api.ts +4 -4
- package/ai/usage.md +8 -1
- package/dist/esm.js +1 -1
- package/dist/umd.js +1 -1
- package/package.json +1 -1
- package/src/AGENTS.md +11 -15
- package/src/Container/Executor.mjs +2 -2
- package/src/Container/GraphResolver.mjs +8 -8
- package/src/Container/Instantiate.mjs +2 -2
- package/src/Container/Lifecycle.mjs +2 -2
- package/src/Container/Pipeline.mjs +4 -4
- package/src/Container.mjs +12 -12
- package/src/Parser.mjs +4 -4
- package/types.d.ts +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.7.0 - 2026-07-10 - As-is injection fix and coverage expansion
|
|
4
|
+
|
|
5
|
+
* Fixed the bug that prevented injecting classes as-is, including named exports resolved without factory wrapping.
|
|
6
|
+
* Aligned container namespace aliases and published type declarations with the actual filesystem layout.
|
|
7
|
+
* Expanded unit and integration coverage for pipeline execution, dependency key generation, dependency declarations, Promise-safe wrappers, and as-is export resolution.
|
|
8
|
+
* Refreshed development dependencies and lockfile metadata before the release.
|
|
9
|
+
* Updated package version metadata to `2.7.0`.
|
|
10
|
+
|
|
3
11
|
## 2.6.2 - 2026-06-08 - Documentation alignment and container simplification
|
|
4
12
|
|
|
5
13
|
* Removed the legacy `setParser()` extension point and flattened the internal container implementation layout.
|
package/ai/dependency-id.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dependency-id.md
|
|
2
2
|
|
|
3
|
-
Version:
|
|
3
|
+
Version: 20260710
|
|
4
4
|
|
|
5
5
|
## Purpose
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ Component order is fixed.
|
|
|
23
23
|
|
|
24
24
|
- `PlatformPrefix` — optional source selector such as `node:` or `npm:`.
|
|
25
25
|
- `ModuleName` — logical module identifier inside a namespace.
|
|
26
|
-
- `__ExportName` — optional named export selector.
|
|
26
|
+
- `__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
27
|
- `Lifecycle` — optional instantiation marker.
|
|
28
28
|
- `WrapperSuffixes` — optional ordered wrapper export names appended after the lifecycle marker.
|
|
29
29
|
|
|
@@ -69,11 +69,15 @@ Named exports are selected with a double underscore separator.
|
|
|
69
69
|
Examples:
|
|
70
70
|
|
|
71
71
|
```txt
|
|
72
|
+
App_Service_User
|
|
72
73
|
App_Service_User$
|
|
74
|
+
App_Service_User__Factory
|
|
73
75
|
App_Service_User__Factory$
|
|
74
76
|
```
|
|
75
77
|
|
|
78
|
+
- `App_Service_User` selects the whole module namespace for as-is resolution (no lifecycle marker, no export name).
|
|
76
79
|
- `App_Service_User$` selects the default export for lifecycle-based composition.
|
|
80
|
+
- `App_Service_User__Factory` selects the named export `Factory` for as-is resolution (no lifecycle marker).
|
|
77
81
|
- `App_Service_User__Factory$` selects the named export `Factory` for lifecycle-based composition.
|
|
78
82
|
|
|
79
83
|
## Lifecycle Markers
|
|
@@ -130,6 +134,7 @@ Important rules:
|
|
|
130
134
|
```txt
|
|
131
135
|
App_Math
|
|
132
136
|
App_Service$
|
|
137
|
+
App_Service__Factory
|
|
133
138
|
App_Service__Factory$
|
|
134
139
|
App_Task$$_wrapLog
|
|
135
140
|
node:fs
|
|
@@ -138,8 +143,9 @@ npm:@humanfs/core
|
|
|
138
143
|
|
|
139
144
|
These examples cover:
|
|
140
145
|
|
|
141
|
-
- as-is module
|
|
146
|
+
- as-is module resolution (whole namespace);
|
|
142
147
|
- singleton composition;
|
|
143
|
-
- named export
|
|
148
|
+
- named export as-is resolution;
|
|
149
|
+
- named export singleton composition;
|
|
144
150
|
- transient composition with wrapper exports;
|
|
145
151
|
- platform module access.
|
package/ai/package-api.ts
CHANGED
|
@@ -280,25 +280,25 @@ export const PACKAGE_API: PackageApiContract = {
|
|
|
280
280
|
reason: 'Internal immutable-core helper. Not exported via package.json.',
|
|
281
281
|
},
|
|
282
282
|
{
|
|
283
|
-
alias: '
|
|
283
|
+
alias: 'TeqFw_Di_Container_Instantiate',
|
|
284
284
|
source: './src/Container/Instantiate.mjs',
|
|
285
285
|
exposure: 'internal',
|
|
286
286
|
reason: 'Internal immutable-core helper. Not exported via package.json.',
|
|
287
287
|
},
|
|
288
288
|
{
|
|
289
|
-
alias: '
|
|
289
|
+
alias: 'TeqFw_Di_Container_Lifecycle',
|
|
290
290
|
source: './src/Container/Lifecycle.mjs',
|
|
291
291
|
exposure: 'internal',
|
|
292
292
|
reason: 'Internal lifecycle cache component. Not exported via package.json.',
|
|
293
293
|
},
|
|
294
294
|
{
|
|
295
|
-
alias: '
|
|
295
|
+
alias: 'TeqFw_Di_Container_GraphResolver',
|
|
296
296
|
source: './src/Container/GraphResolver.mjs',
|
|
297
297
|
exposure: 'internal',
|
|
298
298
|
reason: 'Internal graph builder used by Container.get(). Not exported via package.json.',
|
|
299
299
|
},
|
|
300
300
|
{
|
|
301
|
-
alias: '
|
|
301
|
+
alias: 'TeqFw_Di_Container_Executor',
|
|
302
302
|
source: './src/Container/Executor.mjs',
|
|
303
303
|
exposure: 'internal',
|
|
304
304
|
reason: 'Internal wrapper-stage executor. Not exported via package.json.',
|
package/ai/usage.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# usage.md
|
|
2
2
|
|
|
3
|
-
Version:
|
|
3
|
+
Version: 20260710
|
|
4
4
|
|
|
5
5
|
## Purpose
|
|
6
6
|
|
|
@@ -125,6 +125,13 @@ const runtime = await container.get("App_Module$");
|
|
|
125
125
|
const factory = await container.get("App_Module__Factory$");
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
Without a lifecycle marker, the export is resolved as-is — the class or function itself, not an instance:
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
const FactoryClass = await container.get("App_Module__Factory");
|
|
132
|
+
const factory = new FactoryClass({cast: resolvedCast});
|
|
133
|
+
```
|
|
134
|
+
|
|
128
135
|
## Singleton And Transient
|
|
129
136
|
|
|
130
137
|
Common lifecycle-based compositions:
|
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;null!==d?u=e.FACTORY:p.lifecycleDeclared&&(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,R=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},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},O=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},z=function(e){s&&d.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){O(),z("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){O(),z("addPostprocess()."),r.push(e)},this.addNamespaceRoot=function(e,t,r){O(),z(`addNamespaceRoot('${e}').`),o.push({prefix:e,target:t,defaultExt:r})},this.enableTestMode=function(){O(),z("enableTestMode()."),i=!0},this.enableLogging=function(){O(),s||(s=!0,d=new b,"function"==typeof a.setLogger&&a.setLogger(d),d.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(O(),z(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const r=a.parse(e);n.set(R(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:I,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)),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};
|
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;null!==d?u=e.FACTORY:p.lifecycleDeclared&&(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,R=w,j=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},I=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},O=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},z=function(e){s&&d.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){O(),z("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){O(),z("addPostprocess()."),r.push(e)},this.addNamespaceRoot=function(e,t,r){O(),z(`addNamespaceRoot('${e}').`),o.push({prefix:e,target:t,defaultExt:r})},this.enableTestMode=function(){O(),z("enableTestMode()."),i=!0},this.enableLogging=function(){O(),s||(s=!0,d=new C,"function"==typeof a.setLogger&&a.setLogger(d),d.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(O(),z(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const r=a.parse(e);n.set(R(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:j,applyPreprocess:I,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 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}}}}});
|
package/package.json
CHANGED
package/src/AGENTS.md
CHANGED
|
@@ -14,16 +14,12 @@ This file defines only implementation-level obligations. It does not redefine ar
|
|
|
14
14
|
|
|
15
15
|
The following documents are mandatory:
|
|
16
16
|
|
|
17
|
-
- `ctx/docs/code/structure.md`
|
|
18
|
-
- `ctx/docs/code/container.md`
|
|
19
|
-
- `ctx/docs/code/resolver.md`
|
|
20
|
-
- `ctx/docs/code/parser.md`
|
|
21
|
-
- `ctx/docs/code/depid.md`
|
|
22
|
-
- `ctx/docs/code/testing.md`
|
|
23
|
-
- `ctx/docs/code/jsdoc-spec.md`
|
|
24
|
-
- `ctx/docs/code/convention/es6-modules.md`
|
|
25
|
-
- `ctx/docs/code/convention/teqfw/dto.md`
|
|
26
|
-
- `ctx/docs/code/convention/teqfw/enum.md`
|
|
17
|
+
- `ctx/docs/code/layout/structure.md`
|
|
18
|
+
- `ctx/docs/code/components/container.md`
|
|
19
|
+
- `ctx/docs/code/components/resolver.md`
|
|
20
|
+
- `ctx/docs/code/components/parser.md`
|
|
21
|
+
- `ctx/docs/code/components/depid.md`
|
|
22
|
+
- `ctx/docs/code/layout/testing.md`
|
|
27
23
|
|
|
28
24
|
Agent MUST read and follow them before generating or modifying code.
|
|
29
25
|
|
|
@@ -33,7 +29,7 @@ Deviation from these documents constitutes non-compliance.
|
|
|
33
29
|
|
|
34
30
|
Directory layout, namespace mapping, file naming, dependency direction, and static import rules MUST strictly follow:
|
|
35
31
|
|
|
36
|
-
`ctx/docs/code/structure.md`
|
|
32
|
+
`ctx/docs/code/layout/structure.md`
|
|
37
33
|
|
|
38
34
|
In particular:
|
|
39
35
|
|
|
@@ -50,7 +46,7 @@ Structural violations are execution errors.
|
|
|
50
46
|
|
|
51
47
|
JSDoc is mandatory and governed by:
|
|
52
48
|
|
|
53
|
-
`ctx/docs/code/
|
|
49
|
+
`ctx/docs/code/layout/structure.md` (Section 8)
|
|
54
50
|
|
|
55
51
|
All implementation files MUST:
|
|
56
52
|
|
|
@@ -72,8 +68,8 @@ Absence of required JSDoc constitutes non-compliance.
|
|
|
72
68
|
|
|
73
69
|
All DTO and Enum implementations MUST strictly follow:
|
|
74
70
|
|
|
75
|
-
- `ctx/docs/code/
|
|
76
|
-
- `ctx/docs/code/
|
|
71
|
+
- `ctx/docs/code/components/depid.md`
|
|
72
|
+
- `ctx/docs/code/layout/structure.md`
|
|
77
73
|
|
|
78
74
|
In particular:
|
|
79
75
|
|
|
@@ -116,7 +112,7 @@ Redundant validation logic constitutes architectural violation.
|
|
|
116
112
|
|
|
117
113
|
Unit and integration tests MUST follow:
|
|
118
114
|
|
|
119
|
-
`ctx/docs/code/testing.md`
|
|
115
|
+
`ctx/docs/code/layout/testing.md`
|
|
120
116
|
|
|
121
117
|
For every testable source module, exactly one corresponding unit test MUST exist under `test/unit/`, mirroring directory structure.
|
|
122
118
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @namespace
|
|
4
|
+
* @namespace TeqFw_Di_Container_Executor
|
|
5
5
|
* @description Applies wrapper pipeline to resolved values.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Executes wrapper pipeline declared in `depId.wrappers` using functions
|
|
12
12
|
* exported by the resolved module namespace.
|
|
13
13
|
*/
|
|
14
|
-
export default class
|
|
14
|
+
export default class TeqFw_Di_Container_Executor {
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Creates wrapper executor instance.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @namespace
|
|
4
|
+
* @namespace TeqFw_Di_Container_GraphResolver
|
|
5
5
|
* @description Dependency graph resolver for container preloading.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -13,23 +13,23 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* @typedef {object}
|
|
16
|
+
* @typedef {object} TeqFw_Di_Container_GraphResolver_Dependencies
|
|
17
17
|
* @property {TeqFw_Di_Parser} parser
|
|
18
18
|
* @property {TeqFw_Di_Resolver} resolver
|
|
19
19
|
* @property {{log(message: string): void}|null} [logger]
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* @typedef {{depId: TeqFw_Di_DepId__DTO, namespace: object}}
|
|
23
|
+
* @typedef {{depId: TeqFw_Di_DepId__DTO, namespace: object}} TeqFw_Di_Container_GraphResolver_Node
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import {buildDependencyKey} from '../Internal/DependencyKey.mjs';
|
|
27
27
|
import {readDepsDecl} from '../Internal/DepsDecl.mjs';
|
|
28
28
|
|
|
29
|
-
export default class
|
|
29
|
+
export default class TeqFw_Di_Container_GraphResolver {
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
* @param {
|
|
32
|
+
* @param {TeqFw_Di_Container_GraphResolver_Dependencies} deps
|
|
33
33
|
*/
|
|
34
34
|
constructor({parser, resolver, logger = null}) {
|
|
35
35
|
/** @type {{log(message: string): void}|null} */
|
|
@@ -43,7 +43,7 @@ export default class TeqFw_Di_Container_Resolve_GraphResolver {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* @param {TeqFw_Di_DepId__DTO} depId
|
|
46
|
-
* @param {Map<string,
|
|
46
|
+
* @param {Map<string, TeqFw_Di_Container_GraphResolver_Node>} out
|
|
47
47
|
* @param {Set<string>} stack
|
|
48
48
|
* @param {string[]} chain
|
|
49
49
|
* @returns {Promise<void>}
|
|
@@ -87,10 +87,10 @@ export default class TeqFw_Di_Container_Resolve_GraphResolver {
|
|
|
87
87
|
* Resolves full dependency graph for a root depId.
|
|
88
88
|
*
|
|
89
89
|
* @param {TeqFw_Di_DepId__DTO} depId
|
|
90
|
-
* @returns {Promise<Map<string,
|
|
90
|
+
* @returns {Promise<Map<string, TeqFw_Di_Container_GraphResolver_Node>>}
|
|
91
91
|
*/
|
|
92
92
|
this.resolve = async function (depId) {
|
|
93
|
-
/** @type {Map<string,
|
|
93
|
+
/** @type {Map<string, TeqFw_Di_Container_GraphResolver_Node>} */
|
|
94
94
|
const out = new Map();
|
|
95
95
|
/** @type {Set<string>} */
|
|
96
96
|
const stack = new Set();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @namespace
|
|
4
|
+
* @namespace TeqFw_Di_Container_Instantiate
|
|
5
5
|
* @description Instantiates selected exports using composition rules.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -25,7 +25,7 @@ import TeqFw_Di_Enum_Composition from '../Enum/Composition.mjs';
|
|
|
25
25
|
/**
|
|
26
26
|
* @typedef {CallableFactory | ConstructableFactory} Factory
|
|
27
27
|
*/
|
|
28
|
-
export default class
|
|
28
|
+
export default class TeqFw_Di_Container_Instantiate {
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Creates instantiator instance.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @namespace
|
|
4
|
+
* @namespace TeqFw_Di_Container_Lifecycle
|
|
5
5
|
* @description Lifecycle policy cache for produced values.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -17,7 +17,7 @@ import {buildDependencyKey} from '../Internal/DependencyKey.mjs';
|
|
|
17
17
|
* - transient values are never cached;
|
|
18
18
|
* - as-is composition is returned as produced without lifecycle caching.
|
|
19
19
|
*/
|
|
20
|
-
export default class
|
|
20
|
+
export default class TeqFw_Di_Container_Lifecycle {
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Creates lifecycle registry instance.
|
|
@@ -13,10 +13,10 @@ import {makePromiseSafe} from '../Internal/PromiseSafe.mjs';
|
|
|
13
13
|
* @typedef {object} TeqFw_Di_Container_Pipeline_Context
|
|
14
14
|
* @property {TeqFw_Di_Parser} parser
|
|
15
15
|
* @property {TeqFw_Di_Resolver|undefined} resolver
|
|
16
|
-
* @property {
|
|
17
|
-
* @property {
|
|
18
|
-
* @property {
|
|
19
|
-
* @property {
|
|
16
|
+
* @property {TeqFw_Di_Container_GraphResolver|undefined} graphResolver
|
|
17
|
+
* @property {TeqFw_Di_Container_Lifecycle|undefined} lifecycle
|
|
18
|
+
* @property {TeqFw_Di_Container_Instantiate} instantiator
|
|
19
|
+
* @property {TeqFw_Di_Container_Executor} wrapperExecutor
|
|
20
20
|
* @property {{log(message: string): void, error(message: string, error?: unknown): void}} logger
|
|
21
21
|
* @property {boolean} testMode
|
|
22
22
|
* @property {Map<string, unknown>} mockRegistry
|
package/src/Container.mjs
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
import TeqFw_Di_Parser from './Parser.mjs';
|
|
9
9
|
import {Factory as TeqFw_Di_Dto_Resolver_Config_Factory} from './Dto/Resolver/Config.mjs';
|
|
10
10
|
import TeqFw_Di_Resolver from './Container/Resolver.mjs';
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
11
|
+
import TeqFw_Di_Container_GraphResolver from './Container/GraphResolver.mjs';
|
|
12
|
+
import TeqFw_Di_Container_Instantiate from './Container/Instantiate.mjs';
|
|
13
|
+
import TeqFw_Di_Container_Lifecycle from './Container/Lifecycle.mjs';
|
|
14
|
+
import TeqFw_Di_Container_Executor from './Container/Executor.mjs';
|
|
15
15
|
import {executeContainerPipeline} from './Container/Pipeline.mjs';
|
|
16
16
|
import TeqFw_Di_Internal_Logger, {TeqFw_Di_Internal_Logger_Noop} from './Internal/Logger.mjs';
|
|
17
17
|
import {buildDependencyKey} from './Internal/DependencyKey.mjs';
|
|
@@ -46,16 +46,16 @@ export default class TeqFw_Di_Container {
|
|
|
46
46
|
const configFactory = new TeqFw_Di_Dto_Resolver_Config_Factory();
|
|
47
47
|
/** @type {TeqFw_Di_Resolver|undefined} */
|
|
48
48
|
let resolver;
|
|
49
|
-
/** @type {
|
|
49
|
+
/** @type {TeqFw_Di_Container_GraphResolver|undefined} */
|
|
50
50
|
let graphResolver;
|
|
51
|
-
/** @type {
|
|
51
|
+
/** @type {TeqFw_Di_Container_Lifecycle|undefined} */
|
|
52
52
|
let lifecycle;
|
|
53
53
|
/** @type {{log(message: string): void, error(message: string, error?: unknown): void}} */
|
|
54
54
|
let logger = TeqFw_Di_Internal_Logger_Noop;
|
|
55
|
-
/** @type {
|
|
56
|
-
const instantiator = new
|
|
57
|
-
/** @type {
|
|
58
|
-
const wrapperExecutor = new
|
|
55
|
+
/** @type {TeqFw_Di_Container_Instantiate} */
|
|
56
|
+
const instantiator = new TeqFw_Di_Container_Instantiate();
|
|
57
|
+
/** @type {TeqFw_Di_Container_Executor} */
|
|
58
|
+
const wrapperExecutor = new TeqFw_Di_Container_Executor();
|
|
59
59
|
|
|
60
60
|
const getKey = buildDependencyKey;
|
|
61
61
|
const getMockKey = buildDependencyKey;
|
|
@@ -104,8 +104,8 @@ export default class TeqFw_Di_Container {
|
|
|
104
104
|
const resolverConfig = configFactory.create({namespaces: namespaceRoots});
|
|
105
105
|
if (typeof parser.setLogger === 'function') parser.setLogger(logger);
|
|
106
106
|
resolver = new TeqFw_Di_Resolver({config: resolverConfig, logger});
|
|
107
|
-
graphResolver = new
|
|
108
|
-
lifecycle = new
|
|
107
|
+
graphResolver = new TeqFw_Di_Container_GraphResolver({parser, resolver, logger});
|
|
108
|
+
lifecycle = new TeqFw_Di_Container_Lifecycle(logger);
|
|
109
109
|
};
|
|
110
110
|
|
|
111
111
|
/**
|
package/src/Parser.mjs
CHANGED
|
@@ -163,10 +163,10 @@ export default class TeqFw_Di_Parser {
|
|
|
163
163
|
/** @type {typeof TeqFw_Di_Enum_Composition[keyof typeof TeqFw_Di_Enum_Composition]} */
|
|
164
164
|
let composition = TeqFw_Di_Enum_Composition.AS_IS;
|
|
165
165
|
let exportName = split.exportName;
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
if (lifecycle.lifecycleDeclared) {
|
|
167
|
+
if (exportName === null) {
|
|
168
|
+
exportName = 'default';
|
|
169
|
+
}
|
|
170
170
|
composition = TeqFw_Di_Enum_Composition.FACTORY;
|
|
171
171
|
}
|
|
172
172
|
|
package/types.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
declare global {
|
|
2
2
|
type TeqFw_Di_Config_NamespaceRegistry = import("./src/Config/NamespaceRegistry.mjs").default;
|
|
3
3
|
type TeqFw_Di_Container = import("./src/Container.mjs").default;
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
type
|
|
7
|
-
type
|
|
4
|
+
type TeqFw_Di_Container_Instantiate = import("./src/Container/Instantiate.mjs").default;
|
|
5
|
+
type TeqFw_Di_Container_Lifecycle = import("./src/Container/Lifecycle.mjs").default;
|
|
6
|
+
type TeqFw_Di_Container_GraphResolver = import("./src/Container/GraphResolver.mjs").default;
|
|
7
|
+
type TeqFw_Di_Container_Executor = import("./src/Container/Executor.mjs").default;
|
|
8
8
|
type TeqFw_Di_Parser = import("./src/Parser.mjs").default;
|
|
9
9
|
type TeqFw_Di_DepId = import("./src/Dto/DepId.mjs").default;
|
|
10
10
|
type TeqFw_Di_DepId__DTO = import("./src/Dto/DepId.mjs").default;
|