@asaidimu/utils-artifacts 7.0.3 → 7.0.4

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/index.d.mts CHANGED
@@ -481,9 +481,11 @@ interface ArtifactObserver<TArtifact> {
481
481
  * Subscribes a callback function to be invoked whenever the artifact's
482
482
  * state (instance, error, or readiness) changes.
483
483
  * @param callback The function to call on updates. It receives the new `ResolvedArtifact`.
484
+ * @param eager a boolean indicating whether we should immediately call the
485
+ * callback after subscription. Defaults to `false`
484
486
  * @returns A function to unsubscribe the callback and stop receiving updates.
485
487
  */
486
- subscribe(callback: (artifact: ResolvedArtifact<TArtifact>) => void): () => void;
488
+ subscribe(callback: (artifact: ResolvedArtifact<TArtifact>) => void, eager?: boolean): () => void;
487
489
  /**
488
490
  * Resolves another artifact from the container and registers a dependency on it.
489
491
  * If the dependency changes, the current artifact will be invalidated and rebuilt.
package/index.d.ts CHANGED
@@ -481,9 +481,11 @@ interface ArtifactObserver<TArtifact> {
481
481
  * Subscribes a callback function to be invoked whenever the artifact's
482
482
  * state (instance, error, or readiness) changes.
483
483
  * @param callback The function to call on updates. It receives the new `ResolvedArtifact`.
484
+ * @param eager a boolean indicating whether we should immediately call the
485
+ * callback after subscription. Defaults to `false`
484
486
  * @returns A function to unsubscribe the callback and stop receiving updates.
485
487
  */
486
- subscribe(callback: (artifact: ResolvedArtifact<TArtifact>) => void): () => void;
488
+ subscribe(callback: (artifact: ResolvedArtifact<TArtifact>) => void, eager?: boolean): () => void;
487
489
  /**
488
490
  * Resolves another artifact from the container and registers a dependency on it.
489
491
  * If the dependency changes, the current artifact will be invalidated and rebuilt.
package/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=(e=>(e.Singleton="singleton",e.Transient="transient",e))(e||{}),t=class e extends Error{category;constructor(t,r,s){super(t,{cause:s}),this.name="ArtifactError",this.category=r,Object.setPrototypeOf(this,e.prototype)}},r=class extends t{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system")}},s=class extends t{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system")}},i=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...i}){if(this.artifacts.has(e))throw new s(String(e));const{scope:n,...a}=i,o={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===r||r,...a};return this.artifacts.set(e,o),()=>this.unregister(e)}get(e){if(!this.has(e))throw new r(String(e));return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}async unregister(e){this.artifacts.has(e)&&this.artifacts.delete(e)}size(){return this.artifacts.size}keys(){return Array.from(this.artifacts.keys())}clear(){this.artifacts.clear()}},n=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},a=class extends n{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},o=class extends n{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},c=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(e){this._capacity=e?.capacity??1/0,this._yieldMode=e?.yieldMode??"macrotask"}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const r=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await r;let s;await Promise.race([r.then((()=>clearTimeout(s))),new Promise(((r,i)=>{s=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),i(new a("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},h=class{mutex=new c({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{const t=await e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.promise=null}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}ready(){return this._done}running(){return null!==this.promise&&!this.ready()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,r="Operation timed out"){if(null==t)return e;let s;return Promise.race([e.then((e=>(clearTimeout(s),e))),new Promise(((e,i)=>{s=setTimeout((()=>i(new a(r))),t)}))])}},d=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new c({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new o};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new o;s=await e(),this._lastValue=s,this._lastError=void 0,this._hasRun=!0}catch(e){r=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:s,error:r}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},l=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];function u(e,t){if(!e.length)return;const r=e.slice(),s=t?`[${t}]`:"[ArtifactCleanup]";return async()=>{for(let e=r.length-1;e>=0;e--)try{await r[e]()}catch(t){console.error(`${s} Cleanup error at index ${e}:`,t)}}}async function p(e,t){const r=t?`[${t}]`:"[ArtifactCleanup]";for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${r} Cleanup error at index ${t}:`,e)}}var g=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}}),f=class extends Error{constructor(){super("Build superseded by invalidation"),this.name="SupersededBuildError"}},w=class{constructor(e,t,r,s,i){this.registry=e,this.cache=t,this.graph=r,this.store=s,this.observer=i}async build(e,r){const s=this.cache.get(e);if(s&&null!==s.buildOnce&&s.buildOnce.ready())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const i=this.registry.get(e),n=r?new Set(r):new Set;if(n.has(e))throw new t(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${Array.from(n).join(" -> ")}`,"system");n.add(e);let a=s;return a||(a=this.createCachedArtifact(i),this.cache.set(e,a)),"transient"===i.scope?this.executeBuild(i,a,n):(await a.buildOnce.do((()=>this.executeBuild(i,a,n))),a.stream&&a.streamOnce.do(a.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r))))}async executeBuild(e,r,s){const i=e.key,n=String(i),a="transient"===e.scope;r.buildCount++,r.activeDebounceMs=e.debounce??0;const o=[],c=[];let h=!0;o.push((()=>{h=!1}));let d=null,g=null,w=null;const y=this.graph,m=this.cache,v=this;async function b(e){if(e===i)throw new t(`Artifact "${n}" depends on itself.`,"system");const r=y.wouldCreateCycle(i,e,s);if(r)throw new t(`Adding dependency "${String(e)}" to "${n}" would create a cycle: ${r.join(" -> ")}`,"system");null===g&&(g=new Set),null===w&&(w=new Map),g.add(e);const a=await v.build(e,s),o=m.get(e);return o&&w.set(e,o.version),a}const S={state:()=>v.store.get(!0),previous:r.instance,onCleanup:e=>o.push(e),onDispose:e=>c.push(e),use:async e=>e({resolve:b,require:async e=>{const t=await b(e);if(t.error)throw t.error;return t.instance},select:e=>{const t=function(e,t="."){const r=new Set,s=new Map,i=(e="")=>{if(s.has(e))return s.get(e);const n=new Proxy((()=>{}),{get:(s,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic/math/string operations inside a selector.");if(l.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&r.delete(e),r.add(a),i(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions/methods.")}});return s.set(e,n),n};try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(r)}(e);return null===d&&(d=new Set),t.forEach((e=>d.add(e))),e(v.store.get(!0))}}),stream:e=>{if(a)throw new t(`[ArtifactManager] Illegal stream on transient artifact "${n}"`,"system");const s=async(e,t=void 0)=>{await r.streamSerializer.do((async()=>{void 0!==r.stream&&(r.instance=e,r.error=t,r.version++,this.cache.invalidatePackage(i),await this.processStream(i))}))},o={value:()=>r.instance,get signal(){return r.streamController.signal},set:(...e)=>this.store.set(...e),emit:e=>s(e)};r.stream=async()=>{try{const t=await e(o);t&&r.cleanupFunctions.push(t)}catch(e){await s(void 0,e),await this.invalidate(i,!1,!0)}}}};let _,k,A=0;const C=(e.retries??0)+1;for(;A<C;)try{const r=e.factory(S);if(e.timeout){let t;const s=new Promise(((r,s)=>{t=setTimeout((()=>s(new Error(`Timeout: ${e.timeout}ms`))),e.timeout)}));try{_=await Promise.race([r,s])}finally{clearTimeout(t)}}else _=await r;const s=w?this.detectStaleness(w):null;if(!s){k=void 0;break}if(A++,w?.clear(),A<C)continue;k=new t(`Build stale after all retries: dependency "${String(s)}" changed during build.`,"system")}catch(e){if(e instanceof t)throw e;A++,A>=C&&(k=e)}if(!h)throw await p(o,n),new f;if(a||(this.updateDependencyGraph(i,g??new Set,d??new Set),r.cleanupFunctions=o,r.disposeFunctions=c),k?(r.error=k,r.instance=void 0):(r.instance=_,r.error=void 0),r.version++,this.cache.invalidatePackage(i),a)return{instance:_,cleanup:u(o,String(i)),error:k,ready:!0,invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${String(i)}"`)}}detectStaleness(e){for(const[t,r]of e){const e=this.cache.get(t);if(e&&e.version!==r)return t}return null}async invalidate(e,t=!1,r=!1){const s=this.cache.get(e);if(s)return s.debounceTimer&&(clearTimeout(s.debounceTimer),s.debounceTimer=void 0),!t&&s.activeDebounceMs>0?new Promise(((i,n)=>{s.debounceTimer=setTimeout((()=>{s.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(i).catch(n)}),s.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&await s.invalidationSerializer.do((async()=>{s.version++,await this.cache.invalidateInstance(e);const i=this.graph.iterDependents(e);await Promise.all(Array.from(i).map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Cascade failed for "${String(e)}":`,t)})))));const n=this.registry.get(e);!n||!t&&n.lazy&&!this.hasWatchers(e)||r||await this.build(e).catch((t=>{t instanceof f||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),this.observer.notify(e)}))}async dispose(e){const t=this.cache.get(e);if(!t)return;null===t.buildOnce||(await t.buildOnce.current(),await t.invalidationSerializer.do((async()=>{})),await t.streamOnce.current()),await this.cache.invalidateInstance(e),this.graph.removeNode(e),this.cache.delete(e)}async processStream(e){try{const t=this.graph.iterDependents(e);await Promise.all(Array.from(t).map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Failed to invalidate dependent "${String(e)}":`,t)}))))),this.observer.notify(e)}catch(t){console.error(`[ArtifactManager] Stream propagation error "${e}":`,t)}}updateDependencyGraph(e,t,r){const s=this.cache.get(e);s&&(this.graph.hasNode(e)||this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.stateDependencies=r,r.size>0&&(s.stateUnsubscribe=this.store.watch(Array.from(r),(async()=>{await this.invalidate(e)}))))}createCachedArtifact(e){const t="transient"===e.scope,r={instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce??0,streamController:new AbortController};return t?{...r,buildOnce:null,streamOnce:null,streamSerializer:null,invalidationSerializer:null}:{...r,buildOnce:new h({retry:!0,throws:!0}),streamOnce:new h({retry:!0,throws:!0}),streamSerializer:new d({yieldMode:"microtask"}),invalidationSerializer:new d({yieldMode:"macrotask"})}}hasWatchers(e){return this.observer.hasWatchers(e)??!1}},y=class{dependencies=new Map;dependents=new Map;metadata=new Map;registerNode(e,t){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set),void 0!==t&&this.metadata.set(e,t)}removeNode(e){if(!this.hasNode(e))return;const t=this.dependencies.get(e);if(t)for(const r of t)this.dependents.get(r)?.delete(e);const r=this.dependents.get(e);if(r)for(const t of r)this.dependencies.get(t)?.delete(e);this.dependencies.delete(e),this.dependents.delete(e),this.metadata.delete(e)}hasNode(e){return this.dependencies.has(e)}addDependency(e,t){this.registerNode(e),this.registerNode(t),this.dependencies.get(e).add(t),this.dependents.get(t).add(e)}removeDependency(e,t){this.dependencies.get(e)?.delete(t),this.dependents.get(t)?.delete(e)}getDependencies(e){const t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){const t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??m}iterDependencies(e){return this.dependencies.get(e)??m}getMetadata(e){return this.metadata.get(e)}setMetadata(e,t){this.registerNode(e),this.metadata.set(e,t)}setDependencies(e,t){this.registerNode(e);const r=this.dependencies.get(e),s=new Set(t);for(const t of r)s.has(t)||this.removeDependency(e,t);for(const t of s)r.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const r=[t],s=new Set([t]),i=new Map;for(;r.length>0;){const n=r.shift();if(n===e){const r=[];let s=e;for(;void 0!==s&&(r.push(s),s!==t);)s=i.get(s);return r.reverse(),r.unshift(e),r}const a=this.dependencies.get(n);if(a)for(const e of a)s.has(e)||(s.add(e),i.set(e,n),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const i=this.dependents.get(t);if(i)for(const t of i){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,i=new Set,n=[e];i.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)i.has(e)||(i.add(e),s.add(e),n.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear(),this.metadata.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},m=new Set,v=class{graph;constructor(){this.graph=new y}registerNode(e){this.graph.registerNode(e)}removeNode(e){this.graph.removeNode(e)}addDependency(e,t){this.graph.addDependency(e,t)}removeDependency(e,t){this.graph.removeDependency(e,t)}getDependents(e){const t=this.graph.getDependents(e);return Array.from(t)}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){const t=this.graph.getDependencies(e);return Array.from(t)}getTransitiveDependents(e){const t=this.graph.getTransitiveDependents(e,!1);return new Set(Array.from(t))}setDependencies(e,t){const r=Array.from(t).map((e=>e));this.graph.setDependencies(e,r)}wouldCreateCycle(e,t,r){if(r?.has(t)){const e=Array.from(r),s=e.indexOf(t),i=e.slice(s);return i.push(t),i}const s=this.graph.wouldCreateCycle(e,t);return s||null}hasNode(e){return this.graph.hasNode(e)}getAllNodes(){return this.graph.getAllNodes()}clear(){this.graph.clear()}size(){return this.graph.size()}toDebugString(){return this.graph.toDebugString()}},b=class{cache=new Map;get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t)}delete(e){this.cache.delete(e)}has(e){return this.cache.has(e)}clear(){this.cache.clear()}size(){return this.cache.size}keys(){return Array.from(this.cache.keys())}package(e,t){const r=this.get(e);if(!r)return g;if(r.packagedArtifact)return r.packagedArtifact;const s=String(e);let i=null;const n={instance:r.instance,error:r.error,ready:r.buildOnce?.ready(),get cleanup(){return null===i&&(i=u(r.cleanupFunctions,s)??void 0),i},invalidate:t};return r.packagedArtifact=n,n}invalidatePackage(e){const t=this.get(e);t&&(t.packagedArtifact=void 0)}async invalidateInstance(e){const t=this.get(e);if(!t)return;t.stateUnsubscribe&&(t.stateUnsubscribe(),t.stateUnsubscribe=void 0),t.debounceTimer&&(clearTimeout(t.debounceTimer),t.debounceTimer=void 0);const r=null===t.buildOnce;r||(t.streamController.abort(),await t.streamOnce.current(),t.streamOnce=new h({retry:!0,throws:!0}),t.streamSerializer.close(),t.stream=void 0,t.streamSerializer=new d,t.streamController=new AbortController),await p(t.cleanupFunctions,String(e)),await p(t.disposeFunctions,String(e)),t.cleanupFunctions=[],t.disposeFunctions=[],r||t.buildOnce.reset(),t.instance=void 0,t.error=void 0}},S=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watcherCache=new Map;watch(e){const t=String(e),r=this.registry.get(e);if(!r)throw new Error(`Artifact "${t}" not registered`);const s="transient"===r.scope?`${t}__watched`:t,i="transient"===r.scope;if(this.watcherCache.has(s))return this.watcherCache.get(s).watcher;const n={count:0,init:new h({retry:!1,throws:!0}),watcher:null},a=()=>n.init.do((async()=>{i&&!this.registry.has(s)&&this.registry.register({key:s,factory:r.factory,scope:"singleton",lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce})}));return n.watcher={id:t,get count(){return n.count},get:()=>0===n.count?g:this.cache.package(s,(e=>this.container.invalidate(s,e))),resolve:async()=>(await a(),this.container.resolve(s)),subscribe:e=>{0===n.count&&a(),n.count++,this.listeners.has(s)||this.listeners.set(s,new Set);const t=()=>e(n.watcher.get());return this.container.resolve(s).then((()=>{t(),this.listeners.get(s)?.add(t)})).catch((e=>{console.error(`[ArtifactObserver] Background resolution failed for "${s}":`,e),this.listeners.get(s)?.add(t)})),()=>{this.listeners.get(s)?.delete(t),n.count--,0===n.count&&(this.listeners.delete(s),i&&(this.registry.unregister(s).catch((e=>{console.error(`[ArtifactObserver] Cleanup failed for "${s}":`,e)})),this.cache.delete(s),this.watcherCache.delete(s)),n.init.reset())}}},this.watcherCache.set(s,n),n.watcher}notify(e){const t=this.listeners.get(e);if(t&&0!==t.size)for(const r of t)try{r()}catch(t){console.error(`[ArtifactObserver] Listener error for "${e}":`,t)}}hasWatchers(e){return!!this.watcherCache.has(e)||this.watcherCache.has(`${e}__watched`)}getWatcherCount(e){const t=this.watcherCache.get(e)||this.watcherCache.get(`${e}__watched`);return t?.count??0}clear(){this.watcherCache.clear(),this.listeners.clear()}};exports.ArtifactContainer=class{registry;cache;graph;manager;observer;store;constructor(e){this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t)},this.registry=new i,this.cache=new b,this.graph=new v,this.observer=new S(this.registry,this.cache,this),this.manager=new w(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const r=this.registry.get(t),s=this.cache.get(t);if(!r)return;let i="idle";s&&(void 0!==s.debounceTimer?i="debouncing":s.buildOnce?.running()?i="building":s.buildOnce?.done()&&!s.buildOnce?.ready()?i="pending":s.error?i="error":void 0!==s.instance&&(i="active")),e.push({id:t,scope:r.scope??"singleton",status:i,dependencies:this.graph.getDependencies(t).map((e=>String(e))),dependents:this.graph.getDependents(t).map((e=>String(e))),stateDependencies:s?Array.from(s.stateDependencies):[],buildCount:s?.buildCount??0})})),e}register(e){const{key:t}=e,r=t;this.registry.has(t)&&(console.warn(`[ArtifactContainer] Overwriting "${r}".`),this.manager.dispose(t).catch((e=>{console.error(`[ArtifactContainer] Failed to dispose existing artifact "${r}":`,e)}))),this.registry.register(e),this.graph.registerNode(t);const s=e.scope??"singleton";return(e.lazy??!0)||"singleton"!==s||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${r}":`,e)})),()=>this.unregister(t)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e)}async resolve(e){if(!this.registry.has(e))throw new r(e);return this.manager.build(e)}async require(e){const t=await this.resolve(e);if(t.error)throw t.error;return t.instance}watch(e){if(!this.registry.has(e))throw new r(e);return this.observer.watch(e)}peek(e){const t=this.cache.get(e);if(void 0!==t?.instance)return t?.instance}async invalidate(e,t=!1){return this.manager.invalidate(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){const e=this.registry.keys();await Promise.allSettled(e.map((e=>this.manager.dispose(e).catch((t=>{console.error(`[ArtifactContainer] Failed to dispose artifact "${String(e)}":`,t)}))))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear()}},exports.ArtifactScopes=e;
1
+ "use strict";var e=(e=>(e.Singleton="singleton",e.Transient="transient",e))(e||{}),t=class e extends Error{category;constructor(t,r,s){super(t,{cause:s}),this.name="ArtifactError",this.category=r,Object.setPrototypeOf(this,e.prototype)}},r=class extends t{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system")}},s=class extends t{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system")}},i=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...i}){if(this.artifacts.has(e))throw new s(String(e));const{scope:n,...a}=i,o={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===r||r,...a};return this.artifacts.set(e,o),()=>this.unregister(e)}get(e){if(!this.has(e))throw new r(String(e));return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}async unregister(e){this.artifacts.has(e)&&this.artifacts.delete(e)}size(){return this.artifacts.size}keys(){return Array.from(this.artifacts.keys())}clear(){this.artifacts.clear()}},n=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},a=class extends n{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},o=class extends n{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},c=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(e){this._capacity=e?.capacity??1/0,this._yieldMode=e?.yieldMode??"macrotask"}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const r=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await r;let s;await Promise.race([r.then((()=>clearTimeout(s))),new Promise(((r,i)=>{s=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),i(new a("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},h=class{mutex=new c({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{const t=await e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.promise=null}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}ready(){return this._done}running(){return null!==this.promise&&!this.ready()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,r="Operation timed out"){if(null==t)return e;let s;return Promise.race([e.then((e=>(clearTimeout(s),e))),new Promise(((e,i)=>{s=setTimeout((()=>i(new a(r))),t)}))])}},d=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new c({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new o};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new o;s=await e(),this._lastValue=s,this._lastError=void 0,this._hasRun=!0}catch(e){r=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:s,error:r}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},l=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];function u(e,t){if(!e.length)return;const r=e.slice(),s=t?`[${t}]`:"[ArtifactCleanup]";return async()=>{for(let e=r.length-1;e>=0;e--)try{await r[e]()}catch(t){console.error(`${s} Cleanup error at index ${e}:`,t)}}}async function p(e,t){const r=t?`[${t}]`:"[ArtifactCleanup]";for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${r} Cleanup error at index ${t}:`,e)}}var g=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}}),f=class extends Error{constructor(){super("Build superseded by invalidation"),this.name="SupersededBuildError"}},w=class{constructor(e,t,r,s,i){this.registry=e,this.cache=t,this.graph=r,this.store=s,this.observer=i}async build(e,r){const s=this.cache.get(e);if(s&&null!==s.buildOnce&&s.buildOnce.ready())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const i=this.registry.get(e),n=r?new Set(r):new Set;if(n.has(e))throw new t(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${Array.from(n).join(" -> ")}`,"system");n.add(e);let a=s;return a||(a=this.createCachedArtifact(i),this.cache.set(e,a)),"transient"===i.scope?this.executeBuild(i,a,n):(await a.buildOnce.do((()=>this.executeBuild(i,a,n))),a.stream&&a.streamOnce.do(a.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r))))}async executeBuild(e,r,s){const i=e.key,n=String(i),a="transient"===e.scope;r.buildCount++,r.activeDebounceMs=e.debounce??0;const o=[],c=[];let h=!0;o.push((()=>{h=!1}));let d=null,g=null,w=null;const y=this.graph,m=this.cache,v=this;async function b(e){if(e===i)throw new t(`Artifact "${n}" depends on itself.`,"system");const r=y.wouldCreateCycle(i,e,s);if(r)throw new t(`Adding dependency "${String(e)}" to "${n}" would create a cycle: ${r.join(" -> ")}`,"system");null===g&&(g=new Set),null===w&&(w=new Map),g.add(e);const a=await v.build(e,s),o=m.get(e);return o&&w.set(e,o.version),a}const S={state:()=>v.store.get(!0),previous:r.instance,onCleanup:e=>o.push(e),onDispose:e=>c.push(e),use:async e=>e({resolve:b,require:async e=>{const t=await b(e);if(t.error)throw t.error;return t.instance},select:e=>{const t=function(e,t="."){const r=new Set,s=new Map,i=(e="")=>{if(s.has(e))return s.get(e);const n=new Proxy((()=>{}),{get:(s,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic/math/string operations inside a selector.");if(l.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&r.delete(e),r.add(a),i(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions/methods.")}});return s.set(e,n),n};try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(r)}(e);return null===d&&(d=new Set),t.forEach((e=>d.add(e))),e(v.store.get(!0))}}),stream:e=>{if(a)throw new t(`[ArtifactManager] Illegal stream on transient artifact "${n}"`,"system");const s=async(e,t=void 0)=>{await r.streamSerializer.do((async()=>{void 0!==r.stream&&(r.instance=e,r.error=t,r.version++,this.cache.invalidatePackage(i),await this.processStream(i))}))},o={value:()=>r.instance,get signal(){return r.streamController.signal},set:(...e)=>this.store.set(...e),emit:e=>s(e)};r.stream=async()=>{try{const t=await e(o);t&&r.cleanupFunctions.push(t)}catch(e){await s(void 0,e),await this.invalidate(i,!1,!0)}}}};let _,k,A=0;const C=(e.retries??0)+1;for(;A<C;)try{const r=e.factory(S);if(e.timeout){let t;const s=new Promise(((r,s)=>{t=setTimeout((()=>s(new Error(`Timeout: ${e.timeout}ms`))),e.timeout)}));try{_=await Promise.race([r,s])}finally{clearTimeout(t)}}else _=await r;const s=w?this.detectStaleness(w):null;if(!s){k=void 0;break}if(A++,w?.clear(),A<C)continue;k=new t(`Build stale after all retries: dependency "${String(s)}" changed during build.`,"system")}catch(e){if(e instanceof t)throw e;A++,A>=C&&(k=e)}if(!h)throw await p(o,n),new f;if(a||(this.updateDependencyGraph(i,g??new Set,d??new Set),r.cleanupFunctions=o,r.disposeFunctions=c),k?(r.error=k,r.instance=void 0):(r.instance=_,r.error=void 0),r.version++,this.cache.invalidatePackage(i),a)return{instance:_,cleanup:u(o,String(i)),error:k,ready:!0,invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${String(i)}"`)}}detectStaleness(e){for(const[t,r]of e){const e=this.cache.get(t);if(e&&e.version!==r)return t}return null}async invalidate(e,t=!1,r=!1){const s=this.cache.get(e);if(s)return s.debounceTimer&&(clearTimeout(s.debounceTimer),s.debounceTimer=void 0),!t&&s.activeDebounceMs>0?new Promise(((i,n)=>{s.debounceTimer=setTimeout((()=>{s.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(i).catch(n)}),s.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&await s.invalidationSerializer.do((async()=>{s.version++,await this.cache.invalidateInstance(e);const i=this.graph.iterDependents(e);await Promise.all(Array.from(i).map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Cascade failed for "${String(e)}":`,t)})))));const n=this.registry.get(e);!n||!t&&n.lazy&&!this.hasWatchers(e)||r||await this.build(e).catch((t=>{t instanceof f||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),this.observer.notify(e)}))}async dispose(e){const t=this.cache.get(e);if(!t)return;null===t.buildOnce||(await t.buildOnce.current(),await t.invalidationSerializer.do((async()=>{})),await t.streamOnce.current()),await this.cache.invalidateInstance(e),this.graph.removeNode(e),this.cache.delete(e)}async processStream(e){try{const t=this.graph.iterDependents(e);await Promise.all(Array.from(t).map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Failed to invalidate dependent "${String(e)}":`,t)}))))),this.observer.notify(e)}catch(t){console.error(`[ArtifactManager] Stream propagation error "${e}":`,t)}}updateDependencyGraph(e,t,r){const s=this.cache.get(e);s&&(this.graph.hasNode(e)||this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.stateDependencies=r,r.size>0&&(s.stateUnsubscribe=this.store.watch(Array.from(r),(async()=>{await this.invalidate(e)}))))}createCachedArtifact(e){const t="transient"===e.scope,r={instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce??0,streamController:new AbortController};return t?{...r,buildOnce:null,streamOnce:null,streamSerializer:null,invalidationSerializer:null}:{...r,buildOnce:new h({retry:!0,throws:!0}),streamOnce:new h({retry:!0,throws:!0}),streamSerializer:new d({yieldMode:"microtask"}),invalidationSerializer:new d({yieldMode:"macrotask"})}}hasWatchers(e){return this.observer.hasWatchers(e)??!1}},y=class{dependencies=new Map;dependents=new Map;metadata=new Map;registerNode(e,t){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set),void 0!==t&&this.metadata.set(e,t)}removeNode(e){if(!this.hasNode(e))return;const t=this.dependencies.get(e);if(t)for(const r of t)this.dependents.get(r)?.delete(e);const r=this.dependents.get(e);if(r)for(const t of r)this.dependencies.get(t)?.delete(e);this.dependencies.delete(e),this.dependents.delete(e),this.metadata.delete(e)}hasNode(e){return this.dependencies.has(e)}addDependency(e,t){this.registerNode(e),this.registerNode(t),this.dependencies.get(e).add(t),this.dependents.get(t).add(e)}removeDependency(e,t){this.dependencies.get(e)?.delete(t),this.dependents.get(t)?.delete(e)}getDependencies(e){const t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){const t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??m}iterDependencies(e){return this.dependencies.get(e)??m}getMetadata(e){return this.metadata.get(e)}setMetadata(e,t){this.registerNode(e),this.metadata.set(e,t)}setDependencies(e,t){this.registerNode(e);const r=this.dependencies.get(e),s=new Set(t);for(const t of r)s.has(t)||this.removeDependency(e,t);for(const t of s)r.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const r=[t],s=new Set([t]),i=new Map;for(;r.length>0;){const n=r.shift();if(n===e){const r=[];let s=e;for(;void 0!==s&&(r.push(s),s!==t);)s=i.get(s);return r.reverse(),r.unshift(e),r}const a=this.dependencies.get(n);if(a)for(const e of a)s.has(e)||(s.add(e),i.set(e,n),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const i=this.dependents.get(t);if(i)for(const t of i){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,i=new Set,n=[e];i.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)i.has(e)||(i.add(e),s.add(e),n.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear(),this.metadata.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},m=new Set,v=class{graph;constructor(){this.graph=new y}registerNode(e){this.graph.registerNode(e)}removeNode(e){this.graph.removeNode(e)}addDependency(e,t){this.graph.addDependency(e,t)}removeDependency(e,t){this.graph.removeDependency(e,t)}getDependents(e){const t=this.graph.getDependents(e);return Array.from(t)}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){const t=this.graph.getDependencies(e);return Array.from(t)}getTransitiveDependents(e){const t=this.graph.getTransitiveDependents(e,!1);return new Set(Array.from(t))}setDependencies(e,t){const r=Array.from(t).map((e=>e));this.graph.setDependencies(e,r)}wouldCreateCycle(e,t,r){if(r?.has(t)){const e=Array.from(r),s=e.indexOf(t),i=e.slice(s);return i.push(t),i}const s=this.graph.wouldCreateCycle(e,t);return s||null}hasNode(e){return this.graph.hasNode(e)}getAllNodes(){return this.graph.getAllNodes()}clear(){this.graph.clear()}size(){return this.graph.size()}toDebugString(){return this.graph.toDebugString()}},b=class{cache=new Map;get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t)}delete(e){this.cache.delete(e)}has(e){return this.cache.has(e)}clear(){this.cache.clear()}size(){return this.cache.size}keys(){return Array.from(this.cache.keys())}package(e,t){const r=this.get(e);if(!r)return g;if(r.packagedArtifact)return r.packagedArtifact;const s=String(e);let i=null;const n={instance:r.instance,error:r.error,ready:r.buildOnce?.ready(),get cleanup(){return null===i&&(i=u(r.cleanupFunctions,s)??void 0),i},invalidate:t};return r.packagedArtifact=n,n}invalidatePackage(e){const t=this.get(e);t&&(t.packagedArtifact=void 0)}async invalidateInstance(e){const t=this.get(e);if(!t)return;t.stateUnsubscribe&&(t.stateUnsubscribe(),t.stateUnsubscribe=void 0),t.debounceTimer&&(clearTimeout(t.debounceTimer),t.debounceTimer=void 0);const r=null===t.buildOnce;r||(t.streamController.abort(),await t.streamOnce.current(),t.streamOnce=new h({retry:!0,throws:!0}),t.streamSerializer.close(),t.stream=void 0,t.streamSerializer=new d,t.streamController=new AbortController),await p(t.cleanupFunctions,String(e)),await p(t.disposeFunctions,String(e)),t.cleanupFunctions=[],t.disposeFunctions=[],r||t.buildOnce.reset(),t.instance=void 0,t.error=void 0}},S=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watcherCache=new Map;watch(e){const t=String(e),r=this.registry.get(e);if(!r)throw new Error(`Artifact "${t}" not registered`);const s="transient"===r.scope?`${t}__watched`:t,i="transient"===r.scope;if(this.watcherCache.has(s))return this.watcherCache.get(s).watcher;const n={count:0,init:new h({retry:!1,throws:!0}),watcher:null},a=()=>n.init.do((async()=>{i&&!this.registry.has(s)&&this.registry.register({key:s,factory:r.factory,scope:"singleton",lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce})}));return n.watcher={id:t,get count(){return n.count},get:()=>0===n.count?g:this.cache.package(s,(e=>this.container.invalidate(s,e))),resolve:async()=>(await a(),this.container.resolve(s)),subscribe:(e,t)=>{0===n.count&&a(),n.count++,this.listeners.has(s)||this.listeners.set(s,new Set);const r=()=>e(n.watcher.get());return this.container.resolve(s).then((()=>{t&&r(),this.listeners.get(s)?.add(r)})).catch((e=>{console.error(`[ArtifactObserver] Background resolution failed for "${s}":`,e),this.listeners.get(s)?.add(r)})),()=>{this.listeners.get(s)?.delete(r),n.count--,0===n.count&&(this.listeners.delete(s),i&&(this.registry.unregister(s).catch((e=>{console.error(`[ArtifactObserver] Cleanup failed for "${s}":`,e)})),this.cache.delete(s),this.watcherCache.delete(s)),n.init.reset())}}},this.watcherCache.set(s,n),n.watcher}notify(e){const t=this.listeners.get(e);if(t&&0!==t.size)for(const r of t)try{r()}catch(t){console.error(`[ArtifactObserver] Listener error for "${e}":`,t)}}hasWatchers(e){return!!this.watcherCache.has(e)||this.watcherCache.has(`${e}__watched`)}getWatcherCount(e){const t=this.watcherCache.get(e)||this.watcherCache.get(`${e}__watched`);return t?.count??0}clear(){this.watcherCache.clear(),this.listeners.clear()}};exports.ArtifactContainer=class{registry;cache;graph;manager;observer;store;constructor(e){this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t)},this.registry=new i,this.cache=new b,this.graph=new v,this.observer=new S(this.registry,this.cache,this),this.manager=new w(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const r=this.registry.get(t),s=this.cache.get(t);if(!r)return;let i="idle";s&&(void 0!==s.debounceTimer?i="debouncing":s.buildOnce?.running()?i="building":s.buildOnce?.done()&&!s.buildOnce?.ready()?i="pending":s.error?i="error":void 0!==s.instance&&(i="active")),e.push({id:t,scope:r.scope??"singleton",status:i,dependencies:this.graph.getDependencies(t).map((e=>String(e))),dependents:this.graph.getDependents(t).map((e=>String(e))),stateDependencies:s?Array.from(s.stateDependencies):[],buildCount:s?.buildCount??0})})),e}register(e){const{key:t}=e,r=t;this.registry.has(t)&&(console.warn(`[ArtifactContainer] Overwriting "${r}".`),this.manager.dispose(t).catch((e=>{console.error(`[ArtifactContainer] Failed to dispose existing artifact "${r}":`,e)}))),this.registry.register(e),this.graph.registerNode(t);const s=e.scope??"singleton";return(e.lazy??!0)||"singleton"!==s||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${r}":`,e)})),()=>this.unregister(t)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e)}async resolve(e){if(!this.registry.has(e))throw new r(e);return this.manager.build(e)}async require(e){const t=await this.resolve(e);if(t.error)throw t.error;return t.instance}watch(e){if(!this.registry.has(e))throw new r(e);return this.observer.watch(e)}peek(e){const t=this.cache.get(e);if(void 0!==t?.instance)return t?.instance}async invalidate(e,t=!1){return this.manager.invalidate(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){const e=this.registry.keys();await Promise.allSettled(e.map((e=>this.manager.dispose(e).catch((t=>{console.error(`[ArtifactContainer] Failed to dispose artifact "${String(e)}":`,t)}))))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear()}},exports.ArtifactScopes=e;
package/index.mjs CHANGED
@@ -1 +1 @@
1
- var e=(e=>(e.Singleton="singleton",e.Transient="transient",e))(e||{}),t=class e extends Error{category;constructor(t,r,s){super(t,{cause:s}),this.name="ArtifactError",this.category=r,Object.setPrototypeOf(this,e.prototype)}},r=class extends t{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system")}},s=class extends t{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system")}},i=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...i}){if(this.artifacts.has(e))throw new s(String(e));const{scope:n,...a}=i,o={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===r||r,...a};return this.artifacts.set(e,o),()=>this.unregister(e)}get(e){if(!this.has(e))throw new r(String(e));return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}async unregister(e){this.artifacts.has(e)&&this.artifacts.delete(e)}size(){return this.artifacts.size}keys(){return Array.from(this.artifacts.keys())}clear(){this.artifacts.clear()}},n=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},a=class extends n{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},o=class extends n{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},c=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(e){this._capacity=e?.capacity??1/0,this._yieldMode=e?.yieldMode??"macrotask"}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const r=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await r;let s;await Promise.race([r.then((()=>clearTimeout(s))),new Promise(((r,i)=>{s=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),i(new a("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},h=class{mutex=new c({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{const t=await e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.promise=null}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}ready(){return this._done}running(){return null!==this.promise&&!this.ready()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,r="Operation timed out"){if(null==t)return e;let s;return Promise.race([e.then((e=>(clearTimeout(s),e))),new Promise(((e,i)=>{s=setTimeout((()=>i(new a(r))),t)}))])}},d=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new c({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new o};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new o;s=await e(),this._lastValue=s,this._lastError=void 0,this._hasRun=!0}catch(e){r=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:s,error:r}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},l=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];function u(e,t){if(!e.length)return;const r=e.slice(),s=t?`[${t}]`:"[ArtifactCleanup]";return async()=>{for(let e=r.length-1;e>=0;e--)try{await r[e]()}catch(t){console.error(`${s} Cleanup error at index ${e}:`,t)}}}async function p(e,t){const r=t?`[${t}]`:"[ArtifactCleanup]";for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${r} Cleanup error at index ${t}:`,e)}}var g=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}}),f=class extends Error{constructor(){super("Build superseded by invalidation"),this.name="SupersededBuildError"}},w=class{constructor(e,t,r,s,i){this.registry=e,this.cache=t,this.graph=r,this.store=s,this.observer=i}async build(e,r){const s=this.cache.get(e);if(s&&null!==s.buildOnce&&s.buildOnce.ready())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const i=this.registry.get(e),n=r?new Set(r):new Set;if(n.has(e))throw new t(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${Array.from(n).join(" -> ")}`,"system");n.add(e);let a=s;return a||(a=this.createCachedArtifact(i),this.cache.set(e,a)),"transient"===i.scope?this.executeBuild(i,a,n):(await a.buildOnce.do((()=>this.executeBuild(i,a,n))),a.stream&&a.streamOnce.do(a.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r))))}async executeBuild(e,r,s){const i=e.key,n=String(i),a="transient"===e.scope;r.buildCount++,r.activeDebounceMs=e.debounce??0;const o=[],c=[];let h=!0;o.push((()=>{h=!1}));let d=null,g=null,w=null;const y=this.graph,m=this.cache,v=this;async function b(e){if(e===i)throw new t(`Artifact "${n}" depends on itself.`,"system");const r=y.wouldCreateCycle(i,e,s);if(r)throw new t(`Adding dependency "${String(e)}" to "${n}" would create a cycle: ${r.join(" -> ")}`,"system");null===g&&(g=new Set),null===w&&(w=new Map),g.add(e);const a=await v.build(e,s),o=m.get(e);return o&&w.set(e,o.version),a}const S={state:()=>v.store.get(!0),previous:r.instance,onCleanup:e=>o.push(e),onDispose:e=>c.push(e),use:async e=>e({resolve:b,require:async e=>{const t=await b(e);if(t.error)throw t.error;return t.instance},select:e=>{const t=function(e,t="."){const r=new Set,s=new Map,i=(e="")=>{if(s.has(e))return s.get(e);const n=new Proxy((()=>{}),{get:(s,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic/math/string operations inside a selector.");if(l.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&r.delete(e),r.add(a),i(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions/methods.")}});return s.set(e,n),n};try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(r)}(e);return null===d&&(d=new Set),t.forEach((e=>d.add(e))),e(v.store.get(!0))}}),stream:e=>{if(a)throw new t(`[ArtifactManager] Illegal stream on transient artifact "${n}"`,"system");const s=async(e,t=void 0)=>{await r.streamSerializer.do((async()=>{void 0!==r.stream&&(r.instance=e,r.error=t,r.version++,this.cache.invalidatePackage(i),await this.processStream(i))}))},o={value:()=>r.instance,get signal(){return r.streamController.signal},set:(...e)=>this.store.set(...e),emit:e=>s(e)};r.stream=async()=>{try{const t=await e(o);t&&r.cleanupFunctions.push(t)}catch(e){await s(void 0,e),await this.invalidate(i,!1,!0)}}}};let _,k,A=0;const C=(e.retries??0)+1;for(;A<C;)try{const r=e.factory(S);if(e.timeout){let t;const s=new Promise(((r,s)=>{t=setTimeout((()=>s(new Error(`Timeout: ${e.timeout}ms`))),e.timeout)}));try{_=await Promise.race([r,s])}finally{clearTimeout(t)}}else _=await r;const s=w?this.detectStaleness(w):null;if(!s){k=void 0;break}if(A++,w?.clear(),A<C)continue;k=new t(`Build stale after all retries: dependency "${String(s)}" changed during build.`,"system")}catch(e){if(e instanceof t)throw e;A++,A>=C&&(k=e)}if(!h)throw await p(o,n),new f;if(a||(this.updateDependencyGraph(i,g??new Set,d??new Set),r.cleanupFunctions=o,r.disposeFunctions=c),k?(r.error=k,r.instance=void 0):(r.instance=_,r.error=void 0),r.version++,this.cache.invalidatePackage(i),a)return{instance:_,cleanup:u(o,String(i)),error:k,ready:!0,invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${String(i)}"`)}}detectStaleness(e){for(const[t,r]of e){const e=this.cache.get(t);if(e&&e.version!==r)return t}return null}async invalidate(e,t=!1,r=!1){const s=this.cache.get(e);if(s)return s.debounceTimer&&(clearTimeout(s.debounceTimer),s.debounceTimer=void 0),!t&&s.activeDebounceMs>0?new Promise(((i,n)=>{s.debounceTimer=setTimeout((()=>{s.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(i).catch(n)}),s.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&await s.invalidationSerializer.do((async()=>{s.version++,await this.cache.invalidateInstance(e);const i=this.graph.iterDependents(e);await Promise.all(Array.from(i).map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Cascade failed for "${String(e)}":`,t)})))));const n=this.registry.get(e);!n||!t&&n.lazy&&!this.hasWatchers(e)||r||await this.build(e).catch((t=>{t instanceof f||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),this.observer.notify(e)}))}async dispose(e){const t=this.cache.get(e);if(!t)return;null===t.buildOnce||(await t.buildOnce.current(),await t.invalidationSerializer.do((async()=>{})),await t.streamOnce.current()),await this.cache.invalidateInstance(e),this.graph.removeNode(e),this.cache.delete(e)}async processStream(e){try{const t=this.graph.iterDependents(e);await Promise.all(Array.from(t).map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Failed to invalidate dependent "${String(e)}":`,t)}))))),this.observer.notify(e)}catch(t){console.error(`[ArtifactManager] Stream propagation error "${e}":`,t)}}updateDependencyGraph(e,t,r){const s=this.cache.get(e);s&&(this.graph.hasNode(e)||this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.stateDependencies=r,r.size>0&&(s.stateUnsubscribe=this.store.watch(Array.from(r),(async()=>{await this.invalidate(e)}))))}createCachedArtifact(e){const t="transient"===e.scope,r={instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce??0,streamController:new AbortController};return t?{...r,buildOnce:null,streamOnce:null,streamSerializer:null,invalidationSerializer:null}:{...r,buildOnce:new h({retry:!0,throws:!0}),streamOnce:new h({retry:!0,throws:!0}),streamSerializer:new d({yieldMode:"microtask"}),invalidationSerializer:new d({yieldMode:"macrotask"})}}hasWatchers(e){return this.observer.hasWatchers(e)??!1}},y=class{dependencies=new Map;dependents=new Map;metadata=new Map;registerNode(e,t){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set),void 0!==t&&this.metadata.set(e,t)}removeNode(e){if(!this.hasNode(e))return;const t=this.dependencies.get(e);if(t)for(const r of t)this.dependents.get(r)?.delete(e);const r=this.dependents.get(e);if(r)for(const t of r)this.dependencies.get(t)?.delete(e);this.dependencies.delete(e),this.dependents.delete(e),this.metadata.delete(e)}hasNode(e){return this.dependencies.has(e)}addDependency(e,t){this.registerNode(e),this.registerNode(t),this.dependencies.get(e).add(t),this.dependents.get(t).add(e)}removeDependency(e,t){this.dependencies.get(e)?.delete(t),this.dependents.get(t)?.delete(e)}getDependencies(e){const t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){const t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??m}iterDependencies(e){return this.dependencies.get(e)??m}getMetadata(e){return this.metadata.get(e)}setMetadata(e,t){this.registerNode(e),this.metadata.set(e,t)}setDependencies(e,t){this.registerNode(e);const r=this.dependencies.get(e),s=new Set(t);for(const t of r)s.has(t)||this.removeDependency(e,t);for(const t of s)r.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const r=[t],s=new Set([t]),i=new Map;for(;r.length>0;){const n=r.shift();if(n===e){const r=[];let s=e;for(;void 0!==s&&(r.push(s),s!==t);)s=i.get(s);return r.reverse(),r.unshift(e),r}const a=this.dependencies.get(n);if(a)for(const e of a)s.has(e)||(s.add(e),i.set(e,n),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const i=this.dependents.get(t);if(i)for(const t of i){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,i=new Set,n=[e];i.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)i.has(e)||(i.add(e),s.add(e),n.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear(),this.metadata.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},m=new Set,v=class{graph;constructor(){this.graph=new y}registerNode(e){this.graph.registerNode(e)}removeNode(e){this.graph.removeNode(e)}addDependency(e,t){this.graph.addDependency(e,t)}removeDependency(e,t){this.graph.removeDependency(e,t)}getDependents(e){const t=this.graph.getDependents(e);return Array.from(t)}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){const t=this.graph.getDependencies(e);return Array.from(t)}getTransitiveDependents(e){const t=this.graph.getTransitiveDependents(e,!1);return new Set(Array.from(t))}setDependencies(e,t){const r=Array.from(t).map((e=>e));this.graph.setDependencies(e,r)}wouldCreateCycle(e,t,r){if(r?.has(t)){const e=Array.from(r),s=e.indexOf(t),i=e.slice(s);return i.push(t),i}const s=this.graph.wouldCreateCycle(e,t);return s||null}hasNode(e){return this.graph.hasNode(e)}getAllNodes(){return this.graph.getAllNodes()}clear(){this.graph.clear()}size(){return this.graph.size()}toDebugString(){return this.graph.toDebugString()}},b=class{cache=new Map;get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t)}delete(e){this.cache.delete(e)}has(e){return this.cache.has(e)}clear(){this.cache.clear()}size(){return this.cache.size}keys(){return Array.from(this.cache.keys())}package(e,t){const r=this.get(e);if(!r)return g;if(r.packagedArtifact)return r.packagedArtifact;const s=String(e);let i=null;const n={instance:r.instance,error:r.error,ready:r.buildOnce?.ready(),get cleanup(){return null===i&&(i=u(r.cleanupFunctions,s)??void 0),i},invalidate:t};return r.packagedArtifact=n,n}invalidatePackage(e){const t=this.get(e);t&&(t.packagedArtifact=void 0)}async invalidateInstance(e){const t=this.get(e);if(!t)return;t.stateUnsubscribe&&(t.stateUnsubscribe(),t.stateUnsubscribe=void 0),t.debounceTimer&&(clearTimeout(t.debounceTimer),t.debounceTimer=void 0);const r=null===t.buildOnce;r||(t.streamController.abort(),await t.streamOnce.current(),t.streamOnce=new h({retry:!0,throws:!0}),t.streamSerializer.close(),t.stream=void 0,t.streamSerializer=new d,t.streamController=new AbortController),await p(t.cleanupFunctions,String(e)),await p(t.disposeFunctions,String(e)),t.cleanupFunctions=[],t.disposeFunctions=[],r||t.buildOnce.reset(),t.instance=void 0,t.error=void 0}},S=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watcherCache=new Map;watch(e){const t=String(e),r=this.registry.get(e);if(!r)throw new Error(`Artifact "${t}" not registered`);const s="transient"===r.scope?`${t}__watched`:t,i="transient"===r.scope;if(this.watcherCache.has(s))return this.watcherCache.get(s).watcher;const n={count:0,init:new h({retry:!1,throws:!0}),watcher:null},a=()=>n.init.do((async()=>{i&&!this.registry.has(s)&&this.registry.register({key:s,factory:r.factory,scope:"singleton",lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce})}));return n.watcher={id:t,get count(){return n.count},get:()=>0===n.count?g:this.cache.package(s,(e=>this.container.invalidate(s,e))),resolve:async()=>(await a(),this.container.resolve(s)),subscribe:e=>{0===n.count&&a(),n.count++,this.listeners.has(s)||this.listeners.set(s,new Set);const t=()=>e(n.watcher.get());return this.container.resolve(s).then((()=>{t(),this.listeners.get(s)?.add(t)})).catch((e=>{console.error(`[ArtifactObserver] Background resolution failed for "${s}":`,e),this.listeners.get(s)?.add(t)})),()=>{this.listeners.get(s)?.delete(t),n.count--,0===n.count&&(this.listeners.delete(s),i&&(this.registry.unregister(s).catch((e=>{console.error(`[ArtifactObserver] Cleanup failed for "${s}":`,e)})),this.cache.delete(s),this.watcherCache.delete(s)),n.init.reset())}}},this.watcherCache.set(s,n),n.watcher}notify(e){const t=this.listeners.get(e);if(t&&0!==t.size)for(const r of t)try{r()}catch(t){console.error(`[ArtifactObserver] Listener error for "${e}":`,t)}}hasWatchers(e){return!!this.watcherCache.has(e)||this.watcherCache.has(`${e}__watched`)}getWatcherCount(e){const t=this.watcherCache.get(e)||this.watcherCache.get(`${e}__watched`);return t?.count??0}clear(){this.watcherCache.clear(),this.listeners.clear()}},_=class{registry;cache;graph;manager;observer;store;constructor(e){this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t)},this.registry=new i,this.cache=new b,this.graph=new v,this.observer=new S(this.registry,this.cache,this),this.manager=new w(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const r=this.registry.get(t),s=this.cache.get(t);if(!r)return;let i="idle";s&&(void 0!==s.debounceTimer?i="debouncing":s.buildOnce?.running()?i="building":s.buildOnce?.done()&&!s.buildOnce?.ready()?i="pending":s.error?i="error":void 0!==s.instance&&(i="active")),e.push({id:t,scope:r.scope??"singleton",status:i,dependencies:this.graph.getDependencies(t).map((e=>String(e))),dependents:this.graph.getDependents(t).map((e=>String(e))),stateDependencies:s?Array.from(s.stateDependencies):[],buildCount:s?.buildCount??0})})),e}register(e){const{key:t}=e,r=t;this.registry.has(t)&&(console.warn(`[ArtifactContainer] Overwriting "${r}".`),this.manager.dispose(t).catch((e=>{console.error(`[ArtifactContainer] Failed to dispose existing artifact "${r}":`,e)}))),this.registry.register(e),this.graph.registerNode(t);const s=e.scope??"singleton";return(e.lazy??!0)||"singleton"!==s||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${r}":`,e)})),()=>this.unregister(t)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e)}async resolve(e){if(!this.registry.has(e))throw new r(e);return this.manager.build(e)}async require(e){const t=await this.resolve(e);if(t.error)throw t.error;return t.instance}watch(e){if(!this.registry.has(e))throw new r(e);return this.observer.watch(e)}peek(e){const t=this.cache.get(e);if(void 0!==t?.instance)return t?.instance}async invalidate(e,t=!1){return this.manager.invalidate(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){const e=this.registry.keys();await Promise.allSettled(e.map((e=>this.manager.dispose(e).catch((t=>{console.error(`[ArtifactContainer] Failed to dispose artifact "${String(e)}":`,t)}))))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear()}};export{_ as ArtifactContainer,e as ArtifactScopes};
1
+ var e=(e=>(e.Singleton="singleton",e.Transient="transient",e))(e||{}),t=class e extends Error{category;constructor(t,r,s){super(t,{cause:s}),this.name="ArtifactError",this.category=r,Object.setPrototypeOf(this,e.prototype)}},r=class extends t{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system")}},s=class extends t{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system")}},i=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...i}){if(this.artifacts.has(e))throw new s(String(e));const{scope:n,...a}=i,o={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===r||r,...a};return this.artifacts.set(e,o),()=>this.unregister(e)}get(e){if(!this.has(e))throw new r(String(e));return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}async unregister(e){this.artifacts.has(e)&&this.artifacts.delete(e)}size(){return this.artifacts.size}keys(){return Array.from(this.artifacts.keys())}clear(){this.artifacts.clear()}},n=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},a=class extends n{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},o=class extends n{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},c=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(e){this._capacity=e?.capacity??1/0,this._yieldMode=e?.yieldMode??"macrotask"}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const r=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await r;let s;await Promise.race([r.then((()=>clearTimeout(s))),new Promise(((r,i)=>{s=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),i(new a("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},h=class{mutex=new c({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{const t=await e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.promise=null}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}ready(){return this._done}running(){return null!==this.promise&&!this.ready()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,r="Operation timed out"){if(null==t)return e;let s;return Promise.race([e.then((e=>(clearTimeout(s),e))),new Promise(((e,i)=>{s=setTimeout((()=>i(new a(r))),t)}))])}},d=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new c({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new o};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new o;s=await e(),this._lastValue=s,this._lastError=void 0,this._hasRun=!0}catch(e){r=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:s,error:r}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},l=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];function u(e,t){if(!e.length)return;const r=e.slice(),s=t?`[${t}]`:"[ArtifactCleanup]";return async()=>{for(let e=r.length-1;e>=0;e--)try{await r[e]()}catch(t){console.error(`${s} Cleanup error at index ${e}:`,t)}}}async function p(e,t){const r=t?`[${t}]`:"[ArtifactCleanup]";for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${r} Cleanup error at index ${t}:`,e)}}var g=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}}),f=class extends Error{constructor(){super("Build superseded by invalidation"),this.name="SupersededBuildError"}},w=class{constructor(e,t,r,s,i){this.registry=e,this.cache=t,this.graph=r,this.store=s,this.observer=i}async build(e,r){const s=this.cache.get(e);if(s&&null!==s.buildOnce&&s.buildOnce.ready())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const i=this.registry.get(e),n=r?new Set(r):new Set;if(n.has(e))throw new t(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${Array.from(n).join(" -> ")}`,"system");n.add(e);let a=s;return a||(a=this.createCachedArtifact(i),this.cache.set(e,a)),"transient"===i.scope?this.executeBuild(i,a,n):(await a.buildOnce.do((()=>this.executeBuild(i,a,n))),a.stream&&a.streamOnce.do(a.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r))))}async executeBuild(e,r,s){const i=e.key,n=String(i),a="transient"===e.scope;r.buildCount++,r.activeDebounceMs=e.debounce??0;const o=[],c=[];let h=!0;o.push((()=>{h=!1}));let d=null,g=null,w=null;const y=this.graph,m=this.cache,v=this;async function b(e){if(e===i)throw new t(`Artifact "${n}" depends on itself.`,"system");const r=y.wouldCreateCycle(i,e,s);if(r)throw new t(`Adding dependency "${String(e)}" to "${n}" would create a cycle: ${r.join(" -> ")}`,"system");null===g&&(g=new Set),null===w&&(w=new Map),g.add(e);const a=await v.build(e,s),o=m.get(e);return o&&w.set(e,o.version),a}const S={state:()=>v.store.get(!0),previous:r.instance,onCleanup:e=>o.push(e),onDispose:e=>c.push(e),use:async e=>e({resolve:b,require:async e=>{const t=await b(e);if(t.error)throw t.error;return t.instance},select:e=>{const t=function(e,t="."){const r=new Set,s=new Map,i=(e="")=>{if(s.has(e))return s.get(e);const n=new Proxy((()=>{}),{get:(s,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic/math/string operations inside a selector.");if(l.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&r.delete(e),r.add(a),i(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions/methods.")}});return s.set(e,n),n};try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(r)}(e);return null===d&&(d=new Set),t.forEach((e=>d.add(e))),e(v.store.get(!0))}}),stream:e=>{if(a)throw new t(`[ArtifactManager] Illegal stream on transient artifact "${n}"`,"system");const s=async(e,t=void 0)=>{await r.streamSerializer.do((async()=>{void 0!==r.stream&&(r.instance=e,r.error=t,r.version++,this.cache.invalidatePackage(i),await this.processStream(i))}))},o={value:()=>r.instance,get signal(){return r.streamController.signal},set:(...e)=>this.store.set(...e),emit:e=>s(e)};r.stream=async()=>{try{const t=await e(o);t&&r.cleanupFunctions.push(t)}catch(e){await s(void 0,e),await this.invalidate(i,!1,!0)}}}};let _,k,A=0;const C=(e.retries??0)+1;for(;A<C;)try{const r=e.factory(S);if(e.timeout){let t;const s=new Promise(((r,s)=>{t=setTimeout((()=>s(new Error(`Timeout: ${e.timeout}ms`))),e.timeout)}));try{_=await Promise.race([r,s])}finally{clearTimeout(t)}}else _=await r;const s=w?this.detectStaleness(w):null;if(!s){k=void 0;break}if(A++,w?.clear(),A<C)continue;k=new t(`Build stale after all retries: dependency "${String(s)}" changed during build.`,"system")}catch(e){if(e instanceof t)throw e;A++,A>=C&&(k=e)}if(!h)throw await p(o,n),new f;if(a||(this.updateDependencyGraph(i,g??new Set,d??new Set),r.cleanupFunctions=o,r.disposeFunctions=c),k?(r.error=k,r.instance=void 0):(r.instance=_,r.error=void 0),r.version++,this.cache.invalidatePackage(i),a)return{instance:_,cleanup:u(o,String(i)),error:k,ready:!0,invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${String(i)}"`)}}detectStaleness(e){for(const[t,r]of e){const e=this.cache.get(t);if(e&&e.version!==r)return t}return null}async invalidate(e,t=!1,r=!1){const s=this.cache.get(e);if(s)return s.debounceTimer&&(clearTimeout(s.debounceTimer),s.debounceTimer=void 0),!t&&s.activeDebounceMs>0?new Promise(((i,n)=>{s.debounceTimer=setTimeout((()=>{s.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(i).catch(n)}),s.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&await s.invalidationSerializer.do((async()=>{s.version++,await this.cache.invalidateInstance(e);const i=this.graph.iterDependents(e);await Promise.all(Array.from(i).map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Cascade failed for "${String(e)}":`,t)})))));const n=this.registry.get(e);!n||!t&&n.lazy&&!this.hasWatchers(e)||r||await this.build(e).catch((t=>{t instanceof f||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),this.observer.notify(e)}))}async dispose(e){const t=this.cache.get(e);if(!t)return;null===t.buildOnce||(await t.buildOnce.current(),await t.invalidationSerializer.do((async()=>{})),await t.streamOnce.current()),await this.cache.invalidateInstance(e),this.graph.removeNode(e),this.cache.delete(e)}async processStream(e){try{const t=this.graph.iterDependents(e);await Promise.all(Array.from(t).map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Failed to invalidate dependent "${String(e)}":`,t)}))))),this.observer.notify(e)}catch(t){console.error(`[ArtifactManager] Stream propagation error "${e}":`,t)}}updateDependencyGraph(e,t,r){const s=this.cache.get(e);s&&(this.graph.hasNode(e)||this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.stateDependencies=r,r.size>0&&(s.stateUnsubscribe=this.store.watch(Array.from(r),(async()=>{await this.invalidate(e)}))))}createCachedArtifact(e){const t="transient"===e.scope,r={instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce??0,streamController:new AbortController};return t?{...r,buildOnce:null,streamOnce:null,streamSerializer:null,invalidationSerializer:null}:{...r,buildOnce:new h({retry:!0,throws:!0}),streamOnce:new h({retry:!0,throws:!0}),streamSerializer:new d({yieldMode:"microtask"}),invalidationSerializer:new d({yieldMode:"macrotask"})}}hasWatchers(e){return this.observer.hasWatchers(e)??!1}},y=class{dependencies=new Map;dependents=new Map;metadata=new Map;registerNode(e,t){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set),void 0!==t&&this.metadata.set(e,t)}removeNode(e){if(!this.hasNode(e))return;const t=this.dependencies.get(e);if(t)for(const r of t)this.dependents.get(r)?.delete(e);const r=this.dependents.get(e);if(r)for(const t of r)this.dependencies.get(t)?.delete(e);this.dependencies.delete(e),this.dependents.delete(e),this.metadata.delete(e)}hasNode(e){return this.dependencies.has(e)}addDependency(e,t){this.registerNode(e),this.registerNode(t),this.dependencies.get(e).add(t),this.dependents.get(t).add(e)}removeDependency(e,t){this.dependencies.get(e)?.delete(t),this.dependents.get(t)?.delete(e)}getDependencies(e){const t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){const t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??m}iterDependencies(e){return this.dependencies.get(e)??m}getMetadata(e){return this.metadata.get(e)}setMetadata(e,t){this.registerNode(e),this.metadata.set(e,t)}setDependencies(e,t){this.registerNode(e);const r=this.dependencies.get(e),s=new Set(t);for(const t of r)s.has(t)||this.removeDependency(e,t);for(const t of s)r.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const r=[t],s=new Set([t]),i=new Map;for(;r.length>0;){const n=r.shift();if(n===e){const r=[];let s=e;for(;void 0!==s&&(r.push(s),s!==t);)s=i.get(s);return r.reverse(),r.unshift(e),r}const a=this.dependencies.get(n);if(a)for(const e of a)s.has(e)||(s.add(e),i.set(e,n),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const i=this.dependents.get(t);if(i)for(const t of i){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,i=new Set,n=[e];i.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)i.has(e)||(i.add(e),s.add(e),n.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear(),this.metadata.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},m=new Set,v=class{graph;constructor(){this.graph=new y}registerNode(e){this.graph.registerNode(e)}removeNode(e){this.graph.removeNode(e)}addDependency(e,t){this.graph.addDependency(e,t)}removeDependency(e,t){this.graph.removeDependency(e,t)}getDependents(e){const t=this.graph.getDependents(e);return Array.from(t)}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){const t=this.graph.getDependencies(e);return Array.from(t)}getTransitiveDependents(e){const t=this.graph.getTransitiveDependents(e,!1);return new Set(Array.from(t))}setDependencies(e,t){const r=Array.from(t).map((e=>e));this.graph.setDependencies(e,r)}wouldCreateCycle(e,t,r){if(r?.has(t)){const e=Array.from(r),s=e.indexOf(t),i=e.slice(s);return i.push(t),i}const s=this.graph.wouldCreateCycle(e,t);return s||null}hasNode(e){return this.graph.hasNode(e)}getAllNodes(){return this.graph.getAllNodes()}clear(){this.graph.clear()}size(){return this.graph.size()}toDebugString(){return this.graph.toDebugString()}},b=class{cache=new Map;get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t)}delete(e){this.cache.delete(e)}has(e){return this.cache.has(e)}clear(){this.cache.clear()}size(){return this.cache.size}keys(){return Array.from(this.cache.keys())}package(e,t){const r=this.get(e);if(!r)return g;if(r.packagedArtifact)return r.packagedArtifact;const s=String(e);let i=null;const n={instance:r.instance,error:r.error,ready:r.buildOnce?.ready(),get cleanup(){return null===i&&(i=u(r.cleanupFunctions,s)??void 0),i},invalidate:t};return r.packagedArtifact=n,n}invalidatePackage(e){const t=this.get(e);t&&(t.packagedArtifact=void 0)}async invalidateInstance(e){const t=this.get(e);if(!t)return;t.stateUnsubscribe&&(t.stateUnsubscribe(),t.stateUnsubscribe=void 0),t.debounceTimer&&(clearTimeout(t.debounceTimer),t.debounceTimer=void 0);const r=null===t.buildOnce;r||(t.streamController.abort(),await t.streamOnce.current(),t.streamOnce=new h({retry:!0,throws:!0}),t.streamSerializer.close(),t.stream=void 0,t.streamSerializer=new d,t.streamController=new AbortController),await p(t.cleanupFunctions,String(e)),await p(t.disposeFunctions,String(e)),t.cleanupFunctions=[],t.disposeFunctions=[],r||t.buildOnce.reset(),t.instance=void 0,t.error=void 0}},S=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watcherCache=new Map;watch(e){const t=String(e),r=this.registry.get(e);if(!r)throw new Error(`Artifact "${t}" not registered`);const s="transient"===r.scope?`${t}__watched`:t,i="transient"===r.scope;if(this.watcherCache.has(s))return this.watcherCache.get(s).watcher;const n={count:0,init:new h({retry:!1,throws:!0}),watcher:null},a=()=>n.init.do((async()=>{i&&!this.registry.has(s)&&this.registry.register({key:s,factory:r.factory,scope:"singleton",lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce})}));return n.watcher={id:t,get count(){return n.count},get:()=>0===n.count?g:this.cache.package(s,(e=>this.container.invalidate(s,e))),resolve:async()=>(await a(),this.container.resolve(s)),subscribe:(e,t)=>{0===n.count&&a(),n.count++,this.listeners.has(s)||this.listeners.set(s,new Set);const r=()=>e(n.watcher.get());return this.container.resolve(s).then((()=>{t&&r(),this.listeners.get(s)?.add(r)})).catch((e=>{console.error(`[ArtifactObserver] Background resolution failed for "${s}":`,e),this.listeners.get(s)?.add(r)})),()=>{this.listeners.get(s)?.delete(r),n.count--,0===n.count&&(this.listeners.delete(s),i&&(this.registry.unregister(s).catch((e=>{console.error(`[ArtifactObserver] Cleanup failed for "${s}":`,e)})),this.cache.delete(s),this.watcherCache.delete(s)),n.init.reset())}}},this.watcherCache.set(s,n),n.watcher}notify(e){const t=this.listeners.get(e);if(t&&0!==t.size)for(const r of t)try{r()}catch(t){console.error(`[ArtifactObserver] Listener error for "${e}":`,t)}}hasWatchers(e){return!!this.watcherCache.has(e)||this.watcherCache.has(`${e}__watched`)}getWatcherCount(e){const t=this.watcherCache.get(e)||this.watcherCache.get(`${e}__watched`);return t?.count??0}clear(){this.watcherCache.clear(),this.listeners.clear()}},_=class{registry;cache;graph;manager;observer;store;constructor(e){this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t)},this.registry=new i,this.cache=new b,this.graph=new v,this.observer=new S(this.registry,this.cache,this),this.manager=new w(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const r=this.registry.get(t),s=this.cache.get(t);if(!r)return;let i="idle";s&&(void 0!==s.debounceTimer?i="debouncing":s.buildOnce?.running()?i="building":s.buildOnce?.done()&&!s.buildOnce?.ready()?i="pending":s.error?i="error":void 0!==s.instance&&(i="active")),e.push({id:t,scope:r.scope??"singleton",status:i,dependencies:this.graph.getDependencies(t).map((e=>String(e))),dependents:this.graph.getDependents(t).map((e=>String(e))),stateDependencies:s?Array.from(s.stateDependencies):[],buildCount:s?.buildCount??0})})),e}register(e){const{key:t}=e,r=t;this.registry.has(t)&&(console.warn(`[ArtifactContainer] Overwriting "${r}".`),this.manager.dispose(t).catch((e=>{console.error(`[ArtifactContainer] Failed to dispose existing artifact "${r}":`,e)}))),this.registry.register(e),this.graph.registerNode(t);const s=e.scope??"singleton";return(e.lazy??!0)||"singleton"!==s||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${r}":`,e)})),()=>this.unregister(t)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e)}async resolve(e){if(!this.registry.has(e))throw new r(e);return this.manager.build(e)}async require(e){const t=await this.resolve(e);if(t.error)throw t.error;return t.instance}watch(e){if(!this.registry.has(e))throw new r(e);return this.observer.watch(e)}peek(e){const t=this.cache.get(e);if(void 0!==t?.instance)return t?.instance}async invalidate(e,t=!1){return this.manager.invalidate(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){const e=this.registry.keys();await Promise.allSettled(e.map((e=>this.manager.dispose(e).catch((t=>{console.error(`[ArtifactContainer] Failed to dispose artifact "${String(e)}":`,t)}))))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear()}};export{_ as ArtifactContainer,e as ArtifactScopes};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asaidimu/utils-artifacts",
3
- "version": "7.0.3",
3
+ "version": "7.0.4",
4
4
  "description": "Reactive artifact container.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",