@asaidimu/utils-artifacts 8.1.2 → 8.1.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
@@ -614,7 +614,7 @@ type ArtifactTemplateMap<TState extends object, TRegistry extends Record<string,
614
614
  * @template T The type that contains a factory property.
615
615
  */
616
616
  type ArtifactValue<T> = T extends {
617
- factory: (...args: any[]) => infer TArtifact;
617
+ factory: ArtifactFactory<any, any, infer TArtifact, any>;
618
618
  } ? TArtifact : never;
619
619
  /**
620
620
  * Infers the complete Artifact Registry type from a map of artifact configuration objects.
package/index.d.ts CHANGED
@@ -614,7 +614,7 @@ type ArtifactTemplateMap<TState extends object, TRegistry extends Record<string,
614
614
  * @template T The type that contains a factory property.
615
615
  */
616
616
  type ArtifactValue<T> = T extends {
617
- factory: (...args: any[]) => infer TArtifact;
617
+ factory: ArtifactFactory<any, any, infer TArtifact, any>;
618
618
  } ? TArtifact : never;
619
619
  /**
620
620
  * Infers the complete Artifact Registry type from a map of artifact configuration objects.
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"),this.name="ArtifactNotFoundError"}},s=class extends t{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system"),this.name="ArtifactKeyConflict"}},i=class extends t{constructor(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},n=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,...o}=i,a={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===r||r,...o};return this.artifacts.set(e,a),()=>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()}},o=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];var a=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},c=class extends a{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},h=class extends a{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},d=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 c("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}},l=class{mutex=new d({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{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(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()}running(){return null!==this.promise&&!this.done()}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 c(r))),t)}))])}},u=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new d({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new h};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new h;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()}};function p(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 g(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)}}function f(e){return`${e}__watched`}var w=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function y(e,t){let r;const s=new Promise(((e,s)=>{r=setTimeout((()=>s(new Error(`Timeout: ${t}ms`))),t)}));try{return Promise.race([e,s])}finally{clearTimeout(r)}}var m=(new AbortController).signal,v=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("singleton"===s?.scope&&s.buildOnce.done())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const n=this.registry.get(e),o=r??[];if(o.includes(e))throw new t(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${[...o,e].join(" -> ")}`,"system");o.push(e);let a=s;a||(a=this.createCachedArtifact(n),this.cache.set(e,a));try{if("transient"===a.scope)return this.executeBuild(n,a,o);const t=a;try{await t.buildOnce.do((()=>this.executeBuild(n,t,o)))}catch(t){if(t instanceof i)return this.build(e,r);throw t}return t.stream&&t.streamOnce.do(t.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r)))}finally{o.pop()}}async executeBuild(e,t,r){const s=e.key,i=String(s),n="transient"===t.scope;t.buildCount++,"singleton"===t.scope&&(t.activeDebounceMs=e.debounce??0);const o={cleanupFunctions:[],disposeFunctions:[],capturedStateDeps:new Set,capturedArtifactDeps:new Set,dependencyVersions:new Map},a=this.buildContext(e,t,r,i,o),c=await this.runWithRetries(e,a,o.dependencyVersions);if(this.commitResult(s,t,n,c,o),n){const e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[s]:e,cleanup:p(o.cleanupFunctions,i),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${i}"`)}}}buildContext(e,r,s,i,n){const a=e.key,c="transient"===r.scope,{cleanupFunctions:h,disposeFunctions:d,capturedStateDeps:l,capturedArtifactDeps:u,dependencyVersions:p}=n,g=async e=>{if(e===a)throw new t(`Artifact "${i}" depends on itself.`,"system");const r=this.graph.wouldCreateCycle(a,e);if(r)throw new t(`Adding dependency "${String(e)}" to "${i}" would create a cycle: ${r.join(" -> ")}`,"system");u.add(e);const n=await this.build(e,s),o=this.cache.get(e);return o&&p.set(e,o.version),n},f="singleton"===r.scope?r.controller.signal:m,w=async e=>{const t=await g(e);if(t.error)throw t.error;return t.instance},y=e=>(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, arithmetic, or string operations inside a selector.");if(o.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 or methods.")}});return s.set(e,n),n};try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(r)}(e).forEach((e=>l.add(e))),e(this.store.get(!0)));return{state:()=>this.store.get(!0),previous:r.instance,signal:f,onCleanup:e=>h.push(e),onDispose:e=>d.push(e),use:e=>e({resolve:g,require:w,select:y}),stream:e=>{if(c)throw new t(`[ArtifactManager] Illegal stream on transient artifact "${i}"`,"system");const s=r,n=async(e,t=void 0)=>{await s.streamSerializer.do((async()=>{void 0!==s.stream&&(s.instance=e,s.error=t,s.version++,this.cache.invalidatePackage(a),await this.processStream(i))}))},o={value:()=>s.instance,get signal(){return s.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>n(e)};s.stream=async()=>{try{const t=await e(o);t&&s.cleanupFunctions.push(t)}catch(e){await n(void 0,e),await this.invalidate(a,!1,!0)}}}}}async runWithRetries(e,r,s){const n=r.signal,o=(e.retries??0)+1;let a=0;for(;a<o;)try{if(n.aborted)throw new i;const c=e.factory(r);let h;if(h=c instanceof Promise?e.timeout?await y(c,e.timeout):await c:c,n.aborted)throw new i;const d=this.detectStaleness(s);if(d){if(a++,s.clear(),a<o)continue;return{ok:!1,error:new t(`Build stale after all retries: dependency "${String(d)}" changed during build.`,"system")}}return{ok:!0,value:h}}catch(e){if(n.aborted||e instanceof i)throw new i;if(e instanceof t)throw e;if(a++,a>=o)return{ok:!1,error:e}}return{ok:!1,error:new Error("Build exhausted retry budget unexpectedly.")}}commitResult(e,t,r,s,i){const{cleanupFunctions:n,disposeFunctions:o,capturedArtifactDeps:a,capturedStateDeps:c}=i;r||(this.updateDependencyGraph(e,a,c),t.cleanupFunctions=n,t.disposeFunctions=o),s.ok?(t.instance=s.value,t.error=void 0):(t.instance=void 0,t.error=s.error),t.version++,this.cache.invalidatePackage(e)}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;if("singleton"!==s.scope)return this.executeInvalidation(e,t,r);const i=s;return i.debounceTimer&&(clearTimeout(i.debounceTimer),i.debounceTimer=void 0),!t&&i.activeDebounceMs>0?new Promise(((s,n)=>{i.debounceTimer=setTimeout((()=>{i.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(s).catch(n)}),i.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&"singleton"===s.scope&&await s.invalidationSerializer.do((async()=>{s.version++,await this.cache.invalidateInstance(e),await this.cascadeInvalidation(this.graph.iterDependents(e));const n=this.registry.get(e),o=n&&(t||!n.lazy||this.observer.hasWatchers(e))&&!r;o&&await this.build(e).catch((t=>{t instanceof i||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(o||r)&&this.observer.notify(e)}))}async dispose(e){this.cache.get(e)&&(await this.cache.invalidateInstance(e,!0),this.graph.removeNode(e),this.cache.delete(e))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(0===e.size)return;const t=[];for(const r of e)t.push(this.invalidate(r).catch((e=>{console.error(`[ArtifactManager] Cascade failed for "${String(r)}":`,e)})));await Promise.all(t)}updateDependencyGraph(e,t,r){const s=this.cache.get(e);if(s&&"singleton"===s.scope&&(this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.stateDependencies=r,r.size>0)){const t=Array.from(r),i=()=>this.invalidate(e);s.stateUnsubscribe=this.store.watch(t,i)}}createCachedArtifact(e){return"transient"===e.scope?{scope:"transient",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0}:{scope:"singleton",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce??0,controller:new AbortController,buildOnce:new l({retry:!0,throws:!0}),streamOnce:new l({retry:!0,throws:!0}),streamSerializer:new u({yieldMode:"microtask"}),invalidationSerializer:new u({yieldMode:"macrotask"})}}},b=class{dependencies=new Map;dependents=new Map;registerNode(e){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set)}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)}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)??k}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 o=this.dependencies.get(n);if(o)for(const e of o)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 o="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=o.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()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},k=new Set,_=class{graph;constructor(){this.graph=new b}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){return Array.from(this.graph.getDependents(e))}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){return Array.from(this.graph.getDependencies(e))}getTransitiveDependents(e){return new Set(Array.from(this.graph.getTransitiveDependents(e,!1)))}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()}},S=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 w;if(r.package)return r.package;const s=e,i=p(r.cleanupFunctions,s),n="singleton"!==r.scope||r.buildOnce.done(),o={instance:r.instance,error:r.error,ready:n,[e]:r.instance,cleanup:i,invalidate:t};return r.package=o,o}invalidatePackage(e){const t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(e,t=!1){const r=this.get(e);if(!r)return;const s=e;"singleton"===r.scope&&(r.stateUnsubscribe&&(r.stateUnsubscribe(),r.stateUnsubscribe=void 0),r.debounceTimer&&(clearTimeout(r.debounceTimer),r.debounceTimer=void 0),r.controller.abort(),await r.streamOnce.current(),r.streamSerializer.close(),r.stream=void 0,r.streamOnce=new l({retry:!0,throws:!0}),t||(r.streamSerializer=new u,r.controller=new AbortController)),await g(r.cleanupFunctions,s),await g(r.disposeFunctions,s),r.cleanupFunctions=[],r.disposeFunctions=[],"singleton"===r.scope&&(r.buildOnce=new l({retry:!0,throws:!0})),r.instance=void 0,r.error=void 0}},C=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,i=s?f(t):t;if(this.watcherCache.has(i))return this.watcherCache.get(i).watcher;const n={count:0,init:new l({retry:!1,throws:!0}),watcher:null,pendingReset:!1},o=async()=>{s&&!this.registry.has(i)&&this.registry.register({key:i,factory:r.factory,scope:"singleton",lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce})},a=()=>n.init.do(o);return n.watcher={id:t,get count(){return n.count},get:(e=!1)=>0!==n.count||e?this.cache.package(i,(e=>this.container.invalidate(i,e))):w,resolve:()=>(n.resolve||(n.resolve=a().then((()=>this.container.resolve(i))).finally((()=>{n.resolve=void 0}))),n.resolve),subscribe:(e,t=!0)=>{const r=a();n.pendingReset=!1,n.count++,this.listeners.has(i)||this.listeners.set(i,new Set);const o=()=>e(n.watcher.get());return r.then((()=>this.container.resolve(i))).then((()=>{t&&o(),this.listeners.get(i)?.add(o)})).catch((e=>{console.error(`[ArtifactObserver] Background resolution failed for "${i}":`,e),this.listeners.get(i)?.add(o)})),()=>{if(this.listeners.get(i)?.delete(o),n.count--,0===n.count){if(this.listeners.delete(i),s)return this.registry.unregister(i).catch((e=>{console.error(`[ArtifactObserver] Cleanup failed for "${i}":`,e)})),this.cache.delete(i),void this.watcherCache.delete(i);n.pendingReset=!0,queueMicrotask((()=>{n.pendingReset&&(n.pendingReset=!1,this.cache.invalidatePackage(i),n.init.running()||n.init.reset())}))}}}},this.watcherCache.set(i,n),n.watcher}evictWatcher(e){this.watcherCache.has(e)&&(this.watcherCache.delete(e),this.listeners.delete(e));const t=f(e);this.watcherCache.has(t)&&(this.watcherCache.delete(t),this.listeners.delete(t))}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(f(e))}getWatcherCount(e){const t=this.watcherCache.get(e)||this.watcherCache.get(f(e));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 n,this.cache=new S,this.graph=new _,this.observer=new C(this.registry,this.cache,this),this.manager=new v(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&&("singleton"===s.scope&&void 0!==s.debounceTimer?i="debouncing":"singleton"===s.scope&&s.buildOnce.running()?i="building":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:"singleton"===s?.scope?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)}has(e){return this.registry.has(e)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e),this.observer.evictWatcher(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){return this.cache.get(e)?.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"),this.name="ArtifactNotFoundError"}},s=class extends t{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system"),this.name="ArtifactKeyConflict"}},i=class extends t{constructor(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},n=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,...o}=i,a={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===r||r,...o};return this.artifacts.set(e,a),()=>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()}},o=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];var a=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},c=class extends a{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},h=class extends a{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},d=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 c("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}},l=class{mutex=new d({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{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(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()}running(){return null!==this.promise&&!this.done()}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 c(r))),t)}))])}},u=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new d({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new h};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new h;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()}},p=class{constructor(e,t,r={}){this.factory=e,this.onCleanup=t,this.options=r}_count=0;init=new l({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;const e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){this._count<=0?console.warn("SharedResource.release() called, but count is already 0."):(this._count--,0===this._count&&this.scheduleCleanup())}peek(){const e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,void 0!==this.cleanupTimer&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){const e=this.options.gracePeriod??"microtask";if("sync"!==e)return"microtask"===e?(this.pendingMicrotask=!0,void queueMicrotask((()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())}))):void(this.cleanupTimer=setTimeout((()=>{this.cleanupTimer=void 0,this._count>0||this.executeCleanup()}),e));this.executeCleanup()}executeCleanup(){const e=this.init.peek();try{this.onCleanup(e.value)}catch(e){console.error("[SharedResource] Error during cleanup callback:",e)}this.init.running()||this.init.reset()}};function g(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 f(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)}}function y(e){return`${e}__watched`}var w=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function m(e,t){let r;const s=new Promise(((e,s)=>{r=setTimeout((()=>s(new Error(`Timeout: ${t}ms`))),t)}));try{return Promise.race([e,s])}finally{clearTimeout(r)}}var v=(new AbortController).signal,b=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("singleton"===s?.scope&&s.buildOnce.done())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const n=this.registry.get(e),o=r??[];if(o.includes(e))throw new t(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${[...o,e].join(" -> ")}`,"system");o.push(e);let a=s;a||(a=this.createCachedArtifact(n),this.cache.set(e,a));try{if("transient"===a.scope)return this.executeBuild(n,a,o);const t=a;try{await t.buildOnce.do((()=>this.executeBuild(n,t,o)))}catch(t){if(t instanceof i)return this.build(e,r);throw t}return t.stream&&t.streamOnce.do(t.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r)))}finally{o.pop()}}async executeBuild(e,t,r){const s=e.key,i=String(s),n="transient"===t.scope;t.buildCount++,"singleton"===t.scope&&(t.activeDebounceMs=e.debounce??0);const o={cleanupFunctions:[],disposeFunctions:[],capturedStateDeps:new Set,capturedArtifactDeps:new Set,dependencyVersions:new Map},a=this.buildContext(e,t,r,i,o),c=await this.runWithRetries(e,a,o.dependencyVersions);if(this.commitResult(s,t,n,c,o),n){const e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[s]:e,cleanup:g(o.cleanupFunctions,i),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${i}"`)}}}buildContext(e,r,s,i,n){const a=e.key,c="transient"===r.scope,{cleanupFunctions:h,disposeFunctions:d,capturedStateDeps:l,capturedArtifactDeps:u,dependencyVersions:p}=n,g=async e=>{if(e===a)throw new t(`Artifact "${i}" depends on itself.`,"system");const r=this.graph.wouldCreateCycle(a,e);if(r)throw new t(`Adding dependency "${String(e)}" to "${i}" would create a cycle: ${r.join(" -> ")}`,"system");u.add(e);const n=await this.build(e,s),o=this.cache.get(e);return o&&p.set(e,o.version),n},f="singleton"===r.scope?r.controller.signal:v,y=async e=>{const t=await g(e);if(t.error)throw t.error;return t.instance},w=e=>(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, arithmetic, or string operations inside a selector.");if(o.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 or methods.")}});return s.set(e,n),n};try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(r)}(e).forEach((e=>l.add(e))),e(this.store.get(!0)));return{state:()=>this.store.get(!0),previous:r.instance,signal:f,onCleanup:e=>h.push(e),onDispose:e=>d.push(e),use:e=>e({resolve:g,require:y,select:w}),stream:e=>{if(c)throw new t(`[ArtifactManager] Illegal stream on transient artifact "${i}"`,"system");const s=r,n=async(e,t=void 0)=>{await s.streamSerializer.do((async()=>{void 0!==s.stream&&(s.instance=e,s.error=t,s.version++,this.cache.invalidatePackage(a),await this.processStream(i))}))},o={value:()=>s.instance,get signal(){return s.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>n(e)};s.stream=async()=>{try{const t=await e(o);t&&s.cleanupFunctions.push(t)}catch(e){await n(void 0,e),await this.invalidate(a,!1,!0)}}}}}async runWithRetries(e,r,s){const n=r.signal,o=(e.retries??0)+1;let a=0;for(;a<o;)try{if(n.aborted)throw new i;const c=e.factory(r);let h;if(h=c instanceof Promise?e.timeout?await m(c,e.timeout):await c:c,n.aborted)throw new i;const d=this.detectStaleness(s);if(d){if(a++,s.clear(),a<o)continue;return{ok:!1,error:new t(`Build stale after all retries: dependency "${String(d)}" changed during build.`,"system")}}return{ok:!0,value:h}}catch(e){if(n.aborted||e instanceof i)throw new i;if(e instanceof t)throw e;if(a++,a>=o)return{ok:!1,error:e}}return{ok:!1,error:new Error("Build exhausted retry budget unexpectedly.")}}commitResult(e,t,r,s,i){const{cleanupFunctions:n,disposeFunctions:o,capturedArtifactDeps:a,capturedStateDeps:c}=i;r||(this.updateDependencyGraph(e,a,c),t.cleanupFunctions=n,t.disposeFunctions=o),s.ok?(t.instance=s.value,t.error=void 0):(t.instance=void 0,t.error=s.error),t.version++,this.cache.invalidatePackage(e)}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;if("singleton"!==s.scope)return this.executeInvalidation(e,t,r);const i=s;return i.debounceTimer&&(clearTimeout(i.debounceTimer),i.debounceTimer=void 0),!t&&i.activeDebounceMs>0?new Promise(((s,n)=>{i.debounceTimer=setTimeout((()=>{i.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(s).catch(n)}),i.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&"singleton"===s.scope&&await s.invalidationSerializer.do((async()=>{s.version++,await this.cache.invalidateInstance(e),await this.cascadeInvalidation(this.graph.iterDependents(e));const n=this.registry.get(e),o=n&&(t||!n.lazy||this.observer.hasWatchers(e))&&!r;o&&await this.build(e).catch((t=>{t instanceof i||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(o||r)&&this.observer.notify(e)}))}async dispose(e){this.cache.get(e)&&(await this.cache.invalidateInstance(e,!0),this.graph.removeNode(e),this.cache.delete(e))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(0===e.size)return;const t=[];for(const r of e)t.push(this.invalidate(r).catch((e=>{console.error(`[ArtifactManager] Cascade failed for "${String(r)}":`,e)})));await Promise.all(t)}updateDependencyGraph(e,t,r){const s=this.cache.get(e);if(s&&"singleton"===s.scope&&(this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.stateDependencies=r,r.size>0)){const t=Array.from(r),i=()=>this.invalidate(e);s.stateUnsubscribe=this.store.watch(t,i)}}createCachedArtifact(e){return"transient"===e.scope?{scope:"transient",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0}:{scope:"singleton",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce?e.debounce:0,controller:new AbortController,buildOnce:new l({retry:!0,throws:!0}),streamOnce:new l({retry:!0,throws:!0}),streamSerializer:new u({yieldMode:"microtask"}),invalidationSerializer:new u({yieldMode:"macrotask"})}}},k=class{dependencies=new Map;dependents=new Map;registerNode(e){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set)}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)}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)??_}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 o=this.dependencies.get(n);if(o)for(const e of o)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 o="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=o.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()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},_=new Set,S=class{graph;constructor(){this.graph=new k}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){return Array.from(this.graph.getDependents(e))}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){return Array.from(this.graph.getDependencies(e))}getTransitiveDependents(e){return new Set(Array.from(this.graph.getTransitiveDependents(e,!1)))}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()}},C=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 w;if(r.package)return r.package;const s=e,i=g(r.cleanupFunctions,s),n="singleton"!==r.scope||r.buildOnce.done(),o={instance:r.instance,error:r.error,ready:n,[e]:r.instance,cleanup:i,invalidate:t};return r.package=o,o}invalidatePackage(e){const t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(e,t=!1){const r=this.get(e);if(!r)return;const s=e;"singleton"===r.scope&&(r.stateUnsubscribe&&(r.stateUnsubscribe(),r.stateUnsubscribe=void 0),r.debounceTimer&&(clearTimeout(r.debounceTimer),r.debounceTimer=void 0),r.controller.abort(),await r.streamOnce.current(),r.streamSerializer.close(),r.stream=void 0,r.streamOnce=new l({retry:!0,throws:!0}),t||(r.streamSerializer=new u,r.controller=new AbortController)),await f(r.cleanupFunctions,s),await f(r.disposeFunctions,s),r.cleanupFunctions=[],r.disposeFunctions=[],"singleton"===r.scope&&(r.buildOnce=new l({retry:!0,throws:!0})),r.instance=void 0,r.error=void 0}},x=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watchers=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,i=s?y(t):t,n=this.watchers.get(i);if(n)return n.observer;const o=new p((async()=>{s&&!this.registry.has(i)&&this.registry.register({key:i,factory:r.factory,scope:"singleton",lazy:r.lazy})}),(async()=>{s?(await this.registry.unregister(i).catch((()=>{})),this.cache.delete(i),this.watchers.delete(i)):this.cache.invalidatePackage(i),this.listeners.delete(i)}),{gracePeriod:s?"sync":"microtask"});let a;const c={id:t,get count(){return o.subscribers},get:(e=!1)=>0!==o.subscribers||e?this.cache.package(i,(e=>this.container.invalidate(i,e))):w,resolve:()=>a||(a=(async()=>{await o.acquire();try{return await this.container.resolve(i)}finally{o.release(),a=void 0}})(),a),subscribe:(e,t=!0)=>{const r=()=>e(c.get());return o.acquire().then((()=>this.container.resolve(i))).then((()=>{this.listeners.has(i)||this.listeners.set(i,new Set),t&&r(),this.listeners.get(i)?.add(r)})).catch((e=>{console.error(`[ArtifactObserver] Resolution failed for "${i}":`,e),this.listeners.get(i)?.add(r)})),()=>{this.listeners.get(i)?.delete(r),o.release()}}};return this.watchers.set(i,{resource:o,observer:c}),c}evictWatcher(e){[e,y(e)].forEach((e=>{const t=this.watchers.get(e);t&&(t.resource.forceCleanup(),this.watchers.delete(e))}))}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.watchers.has(e)||this.watchers.has(y(e))}getWatcherCount(e){const t=this.watchers.get(e)||this.watchers.get(y(e));return t?.resource.subscribers??0}clear(){this.watchers.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 n,this.cache=new C,this.graph=new S,this.observer=new x(this.registry,this.cache,this),this.manager=new b(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&&("singleton"===s.scope&&void 0!==s.debounceTimer?i="debouncing":"singleton"===s.scope&&s.buildOnce.running()?i="building":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:"singleton"===s?.scope?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)}has(e){return this.registry.has(e)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e),this.observer.evictWatcher(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){return this.cache.get(e)?.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"),this.name="ArtifactNotFoundError"}},s=class extends t{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system"),this.name="ArtifactKeyConflict"}},i=class extends t{constructor(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},n=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,...o}=i,a={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===r||r,...o};return this.artifacts.set(e,a),()=>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()}},o=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];var a=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},c=class extends a{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},h=class extends a{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},d=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 c("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}},l=class{mutex=new d({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{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(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()}running(){return null!==this.promise&&!this.done()}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 c(r))),t)}))])}},u=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new d({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new h};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new h;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()}};function p(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 g(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)}}function f(e){return`${e}__watched`}var w=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function y(e,t){let r;const s=new Promise(((e,s)=>{r=setTimeout((()=>s(new Error(`Timeout: ${t}ms`))),t)}));try{return Promise.race([e,s])}finally{clearTimeout(r)}}var m=(new AbortController).signal,v=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("singleton"===s?.scope&&s.buildOnce.done())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const n=this.registry.get(e),o=r??[];if(o.includes(e))throw new t(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${[...o,e].join(" -> ")}`,"system");o.push(e);let a=s;a||(a=this.createCachedArtifact(n),this.cache.set(e,a));try{if("transient"===a.scope)return this.executeBuild(n,a,o);const t=a;try{await t.buildOnce.do((()=>this.executeBuild(n,t,o)))}catch(t){if(t instanceof i)return this.build(e,r);throw t}return t.stream&&t.streamOnce.do(t.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r)))}finally{o.pop()}}async executeBuild(e,t,r){const s=e.key,i=String(s),n="transient"===t.scope;t.buildCount++,"singleton"===t.scope&&(t.activeDebounceMs=e.debounce??0);const o={cleanupFunctions:[],disposeFunctions:[],capturedStateDeps:new Set,capturedArtifactDeps:new Set,dependencyVersions:new Map},a=this.buildContext(e,t,r,i,o),c=await this.runWithRetries(e,a,o.dependencyVersions);if(this.commitResult(s,t,n,c,o),n){const e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[s]:e,cleanup:p(o.cleanupFunctions,i),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${i}"`)}}}buildContext(e,r,s,i,n){const a=e.key,c="transient"===r.scope,{cleanupFunctions:h,disposeFunctions:d,capturedStateDeps:l,capturedArtifactDeps:u,dependencyVersions:p}=n,g=async e=>{if(e===a)throw new t(`Artifact "${i}" depends on itself.`,"system");const r=this.graph.wouldCreateCycle(a,e);if(r)throw new t(`Adding dependency "${String(e)}" to "${i}" would create a cycle: ${r.join(" -> ")}`,"system");u.add(e);const n=await this.build(e,s),o=this.cache.get(e);return o&&p.set(e,o.version),n},f="singleton"===r.scope?r.controller.signal:m,w=async e=>{const t=await g(e);if(t.error)throw t.error;return t.instance},y=e=>(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, arithmetic, or string operations inside a selector.");if(o.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 or methods.")}});return s.set(e,n),n};try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(r)}(e).forEach((e=>l.add(e))),e(this.store.get(!0)));return{state:()=>this.store.get(!0),previous:r.instance,signal:f,onCleanup:e=>h.push(e),onDispose:e=>d.push(e),use:e=>e({resolve:g,require:w,select:y}),stream:e=>{if(c)throw new t(`[ArtifactManager] Illegal stream on transient artifact "${i}"`,"system");const s=r,n=async(e,t=void 0)=>{await s.streamSerializer.do((async()=>{void 0!==s.stream&&(s.instance=e,s.error=t,s.version++,this.cache.invalidatePackage(a),await this.processStream(i))}))},o={value:()=>s.instance,get signal(){return s.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>n(e)};s.stream=async()=>{try{const t=await e(o);t&&s.cleanupFunctions.push(t)}catch(e){await n(void 0,e),await this.invalidate(a,!1,!0)}}}}}async runWithRetries(e,r,s){const n=r.signal,o=(e.retries??0)+1;let a=0;for(;a<o;)try{if(n.aborted)throw new i;const c=e.factory(r);let h;if(h=c instanceof Promise?e.timeout?await y(c,e.timeout):await c:c,n.aborted)throw new i;const d=this.detectStaleness(s);if(d){if(a++,s.clear(),a<o)continue;return{ok:!1,error:new t(`Build stale after all retries: dependency "${String(d)}" changed during build.`,"system")}}return{ok:!0,value:h}}catch(e){if(n.aborted||e instanceof i)throw new i;if(e instanceof t)throw e;if(a++,a>=o)return{ok:!1,error:e}}return{ok:!1,error:new Error("Build exhausted retry budget unexpectedly.")}}commitResult(e,t,r,s,i){const{cleanupFunctions:n,disposeFunctions:o,capturedArtifactDeps:a,capturedStateDeps:c}=i;r||(this.updateDependencyGraph(e,a,c),t.cleanupFunctions=n,t.disposeFunctions=o),s.ok?(t.instance=s.value,t.error=void 0):(t.instance=void 0,t.error=s.error),t.version++,this.cache.invalidatePackage(e)}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;if("singleton"!==s.scope)return this.executeInvalidation(e,t,r);const i=s;return i.debounceTimer&&(clearTimeout(i.debounceTimer),i.debounceTimer=void 0),!t&&i.activeDebounceMs>0?new Promise(((s,n)=>{i.debounceTimer=setTimeout((()=>{i.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(s).catch(n)}),i.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&"singleton"===s.scope&&await s.invalidationSerializer.do((async()=>{s.version++,await this.cache.invalidateInstance(e),await this.cascadeInvalidation(this.graph.iterDependents(e));const n=this.registry.get(e),o=n&&(t||!n.lazy||this.observer.hasWatchers(e))&&!r;o&&await this.build(e).catch((t=>{t instanceof i||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(o||r)&&this.observer.notify(e)}))}async dispose(e){this.cache.get(e)&&(await this.cache.invalidateInstance(e,!0),this.graph.removeNode(e),this.cache.delete(e))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(0===e.size)return;const t=[];for(const r of e)t.push(this.invalidate(r).catch((e=>{console.error(`[ArtifactManager] Cascade failed for "${String(r)}":`,e)})));await Promise.all(t)}updateDependencyGraph(e,t,r){const s=this.cache.get(e);if(s&&"singleton"===s.scope&&(this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.stateDependencies=r,r.size>0)){const t=Array.from(r),i=()=>this.invalidate(e);s.stateUnsubscribe=this.store.watch(t,i)}}createCachedArtifact(e){return"transient"===e.scope?{scope:"transient",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0}:{scope:"singleton",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce??0,controller:new AbortController,buildOnce:new l({retry:!0,throws:!0}),streamOnce:new l({retry:!0,throws:!0}),streamSerializer:new u({yieldMode:"microtask"}),invalidationSerializer:new u({yieldMode:"macrotask"})}}},b=class{dependencies=new Map;dependents=new Map;registerNode(e){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set)}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)}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)??k}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 o=this.dependencies.get(n);if(o)for(const e of o)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 o="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=o.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()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},k=new Set,_=class{graph;constructor(){this.graph=new b}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){return Array.from(this.graph.getDependents(e))}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){return Array.from(this.graph.getDependencies(e))}getTransitiveDependents(e){return new Set(Array.from(this.graph.getTransitiveDependents(e,!1)))}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()}},S=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 w;if(r.package)return r.package;const s=e,i=p(r.cleanupFunctions,s),n="singleton"!==r.scope||r.buildOnce.done(),o={instance:r.instance,error:r.error,ready:n,[e]:r.instance,cleanup:i,invalidate:t};return r.package=o,o}invalidatePackage(e){const t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(e,t=!1){const r=this.get(e);if(!r)return;const s=e;"singleton"===r.scope&&(r.stateUnsubscribe&&(r.stateUnsubscribe(),r.stateUnsubscribe=void 0),r.debounceTimer&&(clearTimeout(r.debounceTimer),r.debounceTimer=void 0),r.controller.abort(),await r.streamOnce.current(),r.streamSerializer.close(),r.stream=void 0,r.streamOnce=new l({retry:!0,throws:!0}),t||(r.streamSerializer=new u,r.controller=new AbortController)),await g(r.cleanupFunctions,s),await g(r.disposeFunctions,s),r.cleanupFunctions=[],r.disposeFunctions=[],"singleton"===r.scope&&(r.buildOnce=new l({retry:!0,throws:!0})),r.instance=void 0,r.error=void 0}},C=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,i=s?f(t):t;if(this.watcherCache.has(i))return this.watcherCache.get(i).watcher;const n={count:0,init:new l({retry:!1,throws:!0}),watcher:null,pendingReset:!1},o=async()=>{s&&!this.registry.has(i)&&this.registry.register({key:i,factory:r.factory,scope:"singleton",lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce})},a=()=>n.init.do(o);return n.watcher={id:t,get count(){return n.count},get:(e=!1)=>0!==n.count||e?this.cache.package(i,(e=>this.container.invalidate(i,e))):w,resolve:()=>(n.resolve||(n.resolve=a().then((()=>this.container.resolve(i))).finally((()=>{n.resolve=void 0}))),n.resolve),subscribe:(e,t=!0)=>{const r=a();n.pendingReset=!1,n.count++,this.listeners.has(i)||this.listeners.set(i,new Set);const o=()=>e(n.watcher.get());return r.then((()=>this.container.resolve(i))).then((()=>{t&&o(),this.listeners.get(i)?.add(o)})).catch((e=>{console.error(`[ArtifactObserver] Background resolution failed for "${i}":`,e),this.listeners.get(i)?.add(o)})),()=>{if(this.listeners.get(i)?.delete(o),n.count--,0===n.count){if(this.listeners.delete(i),s)return this.registry.unregister(i).catch((e=>{console.error(`[ArtifactObserver] Cleanup failed for "${i}":`,e)})),this.cache.delete(i),void this.watcherCache.delete(i);n.pendingReset=!0,queueMicrotask((()=>{n.pendingReset&&(n.pendingReset=!1,this.cache.invalidatePackage(i),n.init.running()||n.init.reset())}))}}}},this.watcherCache.set(i,n),n.watcher}evictWatcher(e){this.watcherCache.has(e)&&(this.watcherCache.delete(e),this.listeners.delete(e));const t=f(e);this.watcherCache.has(t)&&(this.watcherCache.delete(t),this.listeners.delete(t))}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(f(e))}getWatcherCount(e){const t=this.watcherCache.get(e)||this.watcherCache.get(f(e));return t?.count??0}clear(){this.watcherCache.clear(),this.listeners.clear()}},A=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 n,this.cache=new S,this.graph=new _,this.observer=new C(this.registry,this.cache,this),this.manager=new v(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&&("singleton"===s.scope&&void 0!==s.debounceTimer?i="debouncing":"singleton"===s.scope&&s.buildOnce.running()?i="building":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:"singleton"===s?.scope?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)}has(e){return this.registry.has(e)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e),this.observer.evictWatcher(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){return this.cache.get(e)?.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{A 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"),this.name="ArtifactNotFoundError"}},s=class extends t{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system"),this.name="ArtifactKeyConflict"}},i=class extends t{constructor(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},n=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,...o}=i,a={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===r||r,...o};return this.artifacts.set(e,a),()=>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()}},o=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];var a=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},c=class extends a{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},h=class extends a{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},d=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 c("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}},l=class{mutex=new d({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{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(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()}running(){return null!==this.promise&&!this.done()}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 c(r))),t)}))])}},u=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new d({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new h};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new h;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()}},p=class{constructor(e,t,r={}){this.factory=e,this.onCleanup=t,this.options=r}_count=0;init=new l({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;const e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){this._count<=0?console.warn("SharedResource.release() called, but count is already 0."):(this._count--,0===this._count&&this.scheduleCleanup())}peek(){const e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,void 0!==this.cleanupTimer&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){const e=this.options.gracePeriod??"microtask";if("sync"!==e)return"microtask"===e?(this.pendingMicrotask=!0,void queueMicrotask((()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())}))):void(this.cleanupTimer=setTimeout((()=>{this.cleanupTimer=void 0,this._count>0||this.executeCleanup()}),e));this.executeCleanup()}executeCleanup(){const e=this.init.peek();try{this.onCleanup(e.value)}catch(e){console.error("[SharedResource] Error during cleanup callback:",e)}this.init.running()||this.init.reset()}};function g(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 f(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)}}function y(e){return`${e}__watched`}var w=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function m(e,t){let r;const s=new Promise(((e,s)=>{r=setTimeout((()=>s(new Error(`Timeout: ${t}ms`))),t)}));try{return Promise.race([e,s])}finally{clearTimeout(r)}}var v=(new AbortController).signal,b=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("singleton"===s?.scope&&s.buildOnce.done())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const n=this.registry.get(e),o=r??[];if(o.includes(e))throw new t(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${[...o,e].join(" -> ")}`,"system");o.push(e);let a=s;a||(a=this.createCachedArtifact(n),this.cache.set(e,a));try{if("transient"===a.scope)return this.executeBuild(n,a,o);const t=a;try{await t.buildOnce.do((()=>this.executeBuild(n,t,o)))}catch(t){if(t instanceof i)return this.build(e,r);throw t}return t.stream&&t.streamOnce.do(t.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r)))}finally{o.pop()}}async executeBuild(e,t,r){const s=e.key,i=String(s),n="transient"===t.scope;t.buildCount++,"singleton"===t.scope&&(t.activeDebounceMs=e.debounce??0);const o={cleanupFunctions:[],disposeFunctions:[],capturedStateDeps:new Set,capturedArtifactDeps:new Set,dependencyVersions:new Map},a=this.buildContext(e,t,r,i,o),c=await this.runWithRetries(e,a,o.dependencyVersions);if(this.commitResult(s,t,n,c,o),n){const e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[s]:e,cleanup:g(o.cleanupFunctions,i),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${i}"`)}}}buildContext(e,r,s,i,n){const a=e.key,c="transient"===r.scope,{cleanupFunctions:h,disposeFunctions:d,capturedStateDeps:l,capturedArtifactDeps:u,dependencyVersions:p}=n,g=async e=>{if(e===a)throw new t(`Artifact "${i}" depends on itself.`,"system");const r=this.graph.wouldCreateCycle(a,e);if(r)throw new t(`Adding dependency "${String(e)}" to "${i}" would create a cycle: ${r.join(" -> ")}`,"system");u.add(e);const n=await this.build(e,s),o=this.cache.get(e);return o&&p.set(e,o.version),n},f="singleton"===r.scope?r.controller.signal:v,y=async e=>{const t=await g(e);if(t.error)throw t.error;return t.instance},w=e=>(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, arithmetic, or string operations inside a selector.");if(o.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 or methods.")}});return s.set(e,n),n};try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(r)}(e).forEach((e=>l.add(e))),e(this.store.get(!0)));return{state:()=>this.store.get(!0),previous:r.instance,signal:f,onCleanup:e=>h.push(e),onDispose:e=>d.push(e),use:e=>e({resolve:g,require:y,select:w}),stream:e=>{if(c)throw new t(`[ArtifactManager] Illegal stream on transient artifact "${i}"`,"system");const s=r,n=async(e,t=void 0)=>{await s.streamSerializer.do((async()=>{void 0!==s.stream&&(s.instance=e,s.error=t,s.version++,this.cache.invalidatePackage(a),await this.processStream(i))}))},o={value:()=>s.instance,get signal(){return s.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>n(e)};s.stream=async()=>{try{const t=await e(o);t&&s.cleanupFunctions.push(t)}catch(e){await n(void 0,e),await this.invalidate(a,!1,!0)}}}}}async runWithRetries(e,r,s){const n=r.signal,o=(e.retries??0)+1;let a=0;for(;a<o;)try{if(n.aborted)throw new i;const c=e.factory(r);let h;if(h=c instanceof Promise?e.timeout?await m(c,e.timeout):await c:c,n.aborted)throw new i;const d=this.detectStaleness(s);if(d){if(a++,s.clear(),a<o)continue;return{ok:!1,error:new t(`Build stale after all retries: dependency "${String(d)}" changed during build.`,"system")}}return{ok:!0,value:h}}catch(e){if(n.aborted||e instanceof i)throw new i;if(e instanceof t)throw e;if(a++,a>=o)return{ok:!1,error:e}}return{ok:!1,error:new Error("Build exhausted retry budget unexpectedly.")}}commitResult(e,t,r,s,i){const{cleanupFunctions:n,disposeFunctions:o,capturedArtifactDeps:a,capturedStateDeps:c}=i;r||(this.updateDependencyGraph(e,a,c),t.cleanupFunctions=n,t.disposeFunctions=o),s.ok?(t.instance=s.value,t.error=void 0):(t.instance=void 0,t.error=s.error),t.version++,this.cache.invalidatePackage(e)}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;if("singleton"!==s.scope)return this.executeInvalidation(e,t,r);const i=s;return i.debounceTimer&&(clearTimeout(i.debounceTimer),i.debounceTimer=void 0),!t&&i.activeDebounceMs>0?new Promise(((s,n)=>{i.debounceTimer=setTimeout((()=>{i.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(s).catch(n)}),i.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&"singleton"===s.scope&&await s.invalidationSerializer.do((async()=>{s.version++,await this.cache.invalidateInstance(e),await this.cascadeInvalidation(this.graph.iterDependents(e));const n=this.registry.get(e),o=n&&(t||!n.lazy||this.observer.hasWatchers(e))&&!r;o&&await this.build(e).catch((t=>{t instanceof i||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(o||r)&&this.observer.notify(e)}))}async dispose(e){this.cache.get(e)&&(await this.cache.invalidateInstance(e,!0),this.graph.removeNode(e),this.cache.delete(e))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(0===e.size)return;const t=[];for(const r of e)t.push(this.invalidate(r).catch((e=>{console.error(`[ArtifactManager] Cascade failed for "${String(r)}":`,e)})));await Promise.all(t)}updateDependencyGraph(e,t,r){const s=this.cache.get(e);if(s&&"singleton"===s.scope&&(this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.stateDependencies=r,r.size>0)){const t=Array.from(r),i=()=>this.invalidate(e);s.stateUnsubscribe=this.store.watch(t,i)}}createCachedArtifact(e){return"transient"===e.scope?{scope:"transient",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0}:{scope:"singleton",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce?e.debounce:0,controller:new AbortController,buildOnce:new l({retry:!0,throws:!0}),streamOnce:new l({retry:!0,throws:!0}),streamSerializer:new u({yieldMode:"microtask"}),invalidationSerializer:new u({yieldMode:"macrotask"})}}},k=class{dependencies=new Map;dependents=new Map;registerNode(e){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set)}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)}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)??_}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 o=this.dependencies.get(n);if(o)for(const e of o)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 o="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=o.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()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},_=new Set,S=class{graph;constructor(){this.graph=new k}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){return Array.from(this.graph.getDependents(e))}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){return Array.from(this.graph.getDependencies(e))}getTransitiveDependents(e){return new Set(Array.from(this.graph.getTransitiveDependents(e,!1)))}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()}},C=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 w;if(r.package)return r.package;const s=e,i=g(r.cleanupFunctions,s),n="singleton"!==r.scope||r.buildOnce.done(),o={instance:r.instance,error:r.error,ready:n,[e]:r.instance,cleanup:i,invalidate:t};return r.package=o,o}invalidatePackage(e){const t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(e,t=!1){const r=this.get(e);if(!r)return;const s=e;"singleton"===r.scope&&(r.stateUnsubscribe&&(r.stateUnsubscribe(),r.stateUnsubscribe=void 0),r.debounceTimer&&(clearTimeout(r.debounceTimer),r.debounceTimer=void 0),r.controller.abort(),await r.streamOnce.current(),r.streamSerializer.close(),r.stream=void 0,r.streamOnce=new l({retry:!0,throws:!0}),t||(r.streamSerializer=new u,r.controller=new AbortController)),await f(r.cleanupFunctions,s),await f(r.disposeFunctions,s),r.cleanupFunctions=[],r.disposeFunctions=[],"singleton"===r.scope&&(r.buildOnce=new l({retry:!0,throws:!0})),r.instance=void 0,r.error=void 0}},x=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watchers=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,i=s?y(t):t,n=this.watchers.get(i);if(n)return n.observer;const o=new p((async()=>{s&&!this.registry.has(i)&&this.registry.register({key:i,factory:r.factory,scope:"singleton",lazy:r.lazy})}),(async()=>{s?(await this.registry.unregister(i).catch((()=>{})),this.cache.delete(i),this.watchers.delete(i)):this.cache.invalidatePackage(i),this.listeners.delete(i)}),{gracePeriod:s?"sync":"microtask"});let a;const c={id:t,get count(){return o.subscribers},get:(e=!1)=>0!==o.subscribers||e?this.cache.package(i,(e=>this.container.invalidate(i,e))):w,resolve:()=>a||(a=(async()=>{await o.acquire();try{return await this.container.resolve(i)}finally{o.release(),a=void 0}})(),a),subscribe:(e,t=!0)=>{const r=()=>e(c.get());return o.acquire().then((()=>this.container.resolve(i))).then((()=>{this.listeners.has(i)||this.listeners.set(i,new Set),t&&r(),this.listeners.get(i)?.add(r)})).catch((e=>{console.error(`[ArtifactObserver] Resolution failed for "${i}":`,e),this.listeners.get(i)?.add(r)})),()=>{this.listeners.get(i)?.delete(r),o.release()}}};return this.watchers.set(i,{resource:o,observer:c}),c}evictWatcher(e){[e,y(e)].forEach((e=>{const t=this.watchers.get(e);t&&(t.resource.forceCleanup(),this.watchers.delete(e))}))}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.watchers.has(e)||this.watchers.has(y(e))}getWatcherCount(e){const t=this.watchers.get(e)||this.watchers.get(y(e));return t?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}},A=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 n,this.cache=new C,this.graph=new S,this.observer=new x(this.registry,this.cache,this),this.manager=new b(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&&("singleton"===s.scope&&void 0!==s.debounceTimer?i="debouncing":"singleton"===s.scope&&s.buildOnce.running()?i="building":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:"singleton"===s?.scope?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)}has(e){return this.registry.has(e)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e),this.observer.evictWatcher(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){return this.cache.get(e)?.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{A as ArtifactContainer,e as ArtifactScopes};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asaidimu/utils-artifacts",
3
- "version": "8.1.2",
3
+ "version": "8.1.4",
4
4
  "description": "Reactive artifact container.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",