@asaidimu/utils-artifacts 8.2.1 → 8.2.3
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 +19 -7
- package/index.d.ts +19 -7
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +2 -2
package/index.d.mts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
interface SubscribeOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Debounce delay in milliseconds. When multiple events arrive in quick
|
|
4
|
+
* succession, the callback runs only after the quiet period ends, using the
|
|
5
|
+
* latest payload. Default = no debouncing.
|
|
6
|
+
*/
|
|
7
|
+
debounce?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
/**
|
|
2
11
|
* Utility type for representing partial updates to the state, allowing deep nesting.
|
|
3
12
|
* It makes all properties optional and applies the same transformation recursively
|
|
@@ -147,9 +156,10 @@ interface DataStore<T extends object> {
|
|
|
147
156
|
* Subscribes a callback to run when the data at the specified path(s) changes.
|
|
148
157
|
* @param path A single path string or an array of path strings to watch.
|
|
149
158
|
* @param callback The function to execute when a change occurs in the watched path(s).
|
|
159
|
+
* @param options Extra options to pass to the event bus
|
|
150
160
|
* @returns An unsubscribe function.
|
|
151
161
|
*/
|
|
152
|
-
watch(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
162
|
+
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
|
|
153
163
|
/**
|
|
154
164
|
* Subscribes to execution‑status changes of a registered action.
|
|
155
165
|
*
|
|
@@ -284,21 +294,23 @@ interface UseDependencyContext<TRegistry extends Record<string, any>, TState ext
|
|
|
284
294
|
* If the dependency changes, the current artifact will be invalidated and rebuilt.
|
|
285
295
|
* @template K The key of the artifact to resolve.
|
|
286
296
|
* @param key The key of the artifact to resolve.
|
|
297
|
+
* @param params Parameters with which to resolve the artifact
|
|
287
298
|
* @returns A Promise that resolves to a `ResolvedArtifact` containing the instance
|
|
288
299
|
* or an external error.
|
|
289
300
|
* @throws {SystemError} if the key is missing or if resolving creates a circular dependency.
|
|
290
301
|
*/
|
|
291
|
-
resolve<K extends keyof TRegistry>(key: K): Promise<ResolvedArtifact<TRegistry[K]>>;
|
|
302
|
+
resolve<K extends keyof TRegistry>(key: K, params?: any): Promise<ResolvedArtifact<TRegistry[K]>>;
|
|
292
303
|
/**
|
|
293
304
|
* Resolves another artifact from the container and registers a dependency on it.
|
|
294
305
|
* If the dependency changes, the current artifact will be invalidated and rebuilt.
|
|
295
306
|
* @template K The key of the artifact to resolve.
|
|
296
307
|
* @param key The key of the artifact to resolve.
|
|
308
|
+
* @param params Parameters with which to resolve the artifact
|
|
297
309
|
* @returns A Promise that resolves to a the resolved instance, unlike
|
|
298
310
|
* resolve, this will throw an error if resolution fails.
|
|
299
311
|
* @throws {SystemError} if any error occurs during resolution.
|
|
300
312
|
*/
|
|
301
|
-
require<K extends keyof TRegistry>(key: K): Promise<TRegistry[K]>;
|
|
313
|
+
require<K extends keyof TRegistry>(key: K, params?: any): Promise<TRegistry[K]>;
|
|
302
314
|
/**
|
|
303
315
|
* Selects a slice of the global state and registers a dependency on it.
|
|
304
316
|
* If the selected state slice changes (based on a deep comparison), the current
|
|
@@ -307,7 +319,7 @@ interface UseDependencyContext<TRegistry extends Record<string, any>, TState ext
|
|
|
307
319
|
* @param selector A function that takes the full state and returns a slice of state.
|
|
308
320
|
* @returns The selected slice of state.
|
|
309
321
|
*/
|
|
310
|
-
select<S>(selector: (state: TState) => S): S;
|
|
322
|
+
select<S>(selector: (state: TState) => S, options?: SubscribeOptions): S;
|
|
311
323
|
}
|
|
312
324
|
/**
|
|
313
325
|
* Context object provided to an artifact stream producer function (`ctx.stream` callback).
|
|
@@ -710,6 +722,7 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
710
722
|
* is needed here.
|
|
711
723
|
*
|
|
712
724
|
* @param key The unique identifier for the artifact
|
|
725
|
+
* @param params Parameters with which to resolve the artifact
|
|
713
726
|
* @returns A Promise that resolves to a ResolvedArtifact
|
|
714
727
|
* @throws {ArtifactNotFoundError} if the artifact is not found
|
|
715
728
|
*/
|
|
@@ -719,6 +732,7 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
719
732
|
* Throws if resolution fails.
|
|
720
733
|
*
|
|
721
734
|
* @param key The unique identifier for the artifact
|
|
735
|
+
* @param params Parameters with which to resolve the artifact
|
|
722
736
|
* @returns A Promise that resolves to the artifact instance
|
|
723
737
|
* @throws {ArtifactNotFoundError} if the artifact is not found
|
|
724
738
|
* @throws the artifact's error if resolution failed
|
|
@@ -729,6 +743,7 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
729
743
|
* The observer allows subscribing to changes in the artifact's resolved value.
|
|
730
744
|
*
|
|
731
745
|
* @param key The unique identifier for the artifact
|
|
746
|
+
* @param params Parameters with which to resolve the artifact
|
|
732
747
|
* @param ttl Delay before the watcher is cleaned up if we have no subscriber
|
|
733
748
|
* @returns An ArtifactObserver instance
|
|
734
749
|
*/
|
|
@@ -775,9 +790,6 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
775
790
|
* Callers should await this method to guarantee full resource release.
|
|
776
791
|
*/
|
|
777
792
|
dispose(): Promise<void>;
|
|
778
|
-
private resolveStatic;
|
|
779
|
-
private resolveParameterized;
|
|
780
|
-
private computeParamKey;
|
|
781
793
|
}
|
|
782
794
|
|
|
783
795
|
export { type ArtifactCleanup, ArtifactContainer, type ArtifactDebugNode, type ArtifactFactory, type ArtifactFactoryContext, type ArtifactInstance, type ArtifactKey, type ArtifactObserver, type ArtifactRegistryType, type ArtifactScope, type ArtifactScopeType, ArtifactScopes, type ArtifactStateType, type ArtifactStreamContext, type ArtifactTemplate, type ArtifactTemplateMap, type ArtifactValue, type ErrorArtifact, type InferRegistry, type KeyedResolvedArtifact, type PendingArtifact, type ReadyArtifact, type ResolvedArtifact, type ResolvedArtifactBase, type UseDependencyContext };
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
interface SubscribeOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Debounce delay in milliseconds. When multiple events arrive in quick
|
|
4
|
+
* succession, the callback runs only after the quiet period ends, using the
|
|
5
|
+
* latest payload. Default = no debouncing.
|
|
6
|
+
*/
|
|
7
|
+
debounce?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
/**
|
|
2
11
|
* Utility type for representing partial updates to the state, allowing deep nesting.
|
|
3
12
|
* It makes all properties optional and applies the same transformation recursively
|
|
@@ -147,9 +156,10 @@ interface DataStore<T extends object> {
|
|
|
147
156
|
* Subscribes a callback to run when the data at the specified path(s) changes.
|
|
148
157
|
* @param path A single path string or an array of path strings to watch.
|
|
149
158
|
* @param callback The function to execute when a change occurs in the watched path(s).
|
|
159
|
+
* @param options Extra options to pass to the event bus
|
|
150
160
|
* @returns An unsubscribe function.
|
|
151
161
|
*/
|
|
152
|
-
watch(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
162
|
+
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
|
|
153
163
|
/**
|
|
154
164
|
* Subscribes to execution‑status changes of a registered action.
|
|
155
165
|
*
|
|
@@ -284,21 +294,23 @@ interface UseDependencyContext<TRegistry extends Record<string, any>, TState ext
|
|
|
284
294
|
* If the dependency changes, the current artifact will be invalidated and rebuilt.
|
|
285
295
|
* @template K The key of the artifact to resolve.
|
|
286
296
|
* @param key The key of the artifact to resolve.
|
|
297
|
+
* @param params Parameters with which to resolve the artifact
|
|
287
298
|
* @returns A Promise that resolves to a `ResolvedArtifact` containing the instance
|
|
288
299
|
* or an external error.
|
|
289
300
|
* @throws {SystemError} if the key is missing or if resolving creates a circular dependency.
|
|
290
301
|
*/
|
|
291
|
-
resolve<K extends keyof TRegistry>(key: K): Promise<ResolvedArtifact<TRegistry[K]>>;
|
|
302
|
+
resolve<K extends keyof TRegistry>(key: K, params?: any): Promise<ResolvedArtifact<TRegistry[K]>>;
|
|
292
303
|
/**
|
|
293
304
|
* Resolves another artifact from the container and registers a dependency on it.
|
|
294
305
|
* If the dependency changes, the current artifact will be invalidated and rebuilt.
|
|
295
306
|
* @template K The key of the artifact to resolve.
|
|
296
307
|
* @param key The key of the artifact to resolve.
|
|
308
|
+
* @param params Parameters with which to resolve the artifact
|
|
297
309
|
* @returns A Promise that resolves to a the resolved instance, unlike
|
|
298
310
|
* resolve, this will throw an error if resolution fails.
|
|
299
311
|
* @throws {SystemError} if any error occurs during resolution.
|
|
300
312
|
*/
|
|
301
|
-
require<K extends keyof TRegistry>(key: K): Promise<TRegistry[K]>;
|
|
313
|
+
require<K extends keyof TRegistry>(key: K, params?: any): Promise<TRegistry[K]>;
|
|
302
314
|
/**
|
|
303
315
|
* Selects a slice of the global state and registers a dependency on it.
|
|
304
316
|
* If the selected state slice changes (based on a deep comparison), the current
|
|
@@ -307,7 +319,7 @@ interface UseDependencyContext<TRegistry extends Record<string, any>, TState ext
|
|
|
307
319
|
* @param selector A function that takes the full state and returns a slice of state.
|
|
308
320
|
* @returns The selected slice of state.
|
|
309
321
|
*/
|
|
310
|
-
select<S>(selector: (state: TState) => S): S;
|
|
322
|
+
select<S>(selector: (state: TState) => S, options?: SubscribeOptions): S;
|
|
311
323
|
}
|
|
312
324
|
/**
|
|
313
325
|
* Context object provided to an artifact stream producer function (`ctx.stream` callback).
|
|
@@ -710,6 +722,7 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
710
722
|
* is needed here.
|
|
711
723
|
*
|
|
712
724
|
* @param key The unique identifier for the artifact
|
|
725
|
+
* @param params Parameters with which to resolve the artifact
|
|
713
726
|
* @returns A Promise that resolves to a ResolvedArtifact
|
|
714
727
|
* @throws {ArtifactNotFoundError} if the artifact is not found
|
|
715
728
|
*/
|
|
@@ -719,6 +732,7 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
719
732
|
* Throws if resolution fails.
|
|
720
733
|
*
|
|
721
734
|
* @param key The unique identifier for the artifact
|
|
735
|
+
* @param params Parameters with which to resolve the artifact
|
|
722
736
|
* @returns A Promise that resolves to the artifact instance
|
|
723
737
|
* @throws {ArtifactNotFoundError} if the artifact is not found
|
|
724
738
|
* @throws the artifact's error if resolution failed
|
|
@@ -729,6 +743,7 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
729
743
|
* The observer allows subscribing to changes in the artifact's resolved value.
|
|
730
744
|
*
|
|
731
745
|
* @param key The unique identifier for the artifact
|
|
746
|
+
* @param params Parameters with which to resolve the artifact
|
|
732
747
|
* @param ttl Delay before the watcher is cleaned up if we have no subscriber
|
|
733
748
|
* @returns An ArtifactObserver instance
|
|
734
749
|
*/
|
|
@@ -775,9 +790,6 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
775
790
|
* Callers should await this method to guarantee full resource release.
|
|
776
791
|
*/
|
|
777
792
|
dispose(): Promise<void>;
|
|
778
|
-
private resolveStatic;
|
|
779
|
-
private resolveParameterized;
|
|
780
|
-
private computeParamKey;
|
|
781
793
|
}
|
|
782
794
|
|
|
783
795
|
export { type ArtifactCleanup, ArtifactContainer, type ArtifactDebugNode, type ArtifactFactory, type ArtifactFactoryContext, type ArtifactInstance, type ArtifactKey, type ArtifactObserver, type ArtifactRegistryType, type ArtifactScope, type ArtifactScopeType, ArtifactScopes, type ArtifactStateType, type ArtifactStreamContext, type ArtifactTemplate, type ArtifactTemplateMap, type ArtifactValue, type ErrorArtifact, type InferRegistry, type KeyedResolvedArtifact, type PendingArtifact, type ReadyArtifact, type ResolvedArtifact, type ResolvedArtifactBase, type UseDependencyContext };
|
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(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},i=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...s}){const{scope:i,...n}=s,a={key:e,factory:t,scope:s.scope??"singleton",lazy:void 0===r||r,...n};return this.artifacts.set(e,a),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw new r(String(e));return this.artifacts.get(e)}getByString(e){return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}hasString(e){return this.artifacts.has(e)}async unregister(e){this.artifacts.has(e)&&this.artifacts.delete(e)}size(){return this.artifacts.size}keys(){return Array.from(this.artifacts.keys())}clear(){this.artifacts.clear()}},n=["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)}},o=class extends a{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},c=class extends a{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},h=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 o("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}},d=class{mutex=new h({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 o(r))),t)}))])}},u=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new h({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new c};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new c;s=await e(),this._lastValue=s,this._lastError=void 0,this._hasRun=!0}catch(e){r=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:s,error:r}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},l=class{constructor(e,t,r={}){this.factory=e,this.onCleanup=t,this.options=r}_count=0;init=new d({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 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 y(e){return`${e}__watched`}var f=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function w(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,i){const n=this.cache.get(e);if("singleton"===n?.scope&&n.buildOnce.done())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const a=this.registry.getByString(e);if(!a)throw new r(e);const o=i??[];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 c=n;c||(c=this.createCachedArtifact(a),this.cache.set(e,c));try{if("transient"===c.scope)return this.executeBuild(a,c,o);const t=c;try{await t.buildOnce.do((()=>this.executeBuild(a,t,o)))}catch(t){if(t instanceof s)return this.build(e,i);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 a={cleanupFunctions:[],disposeFunctions:[],capturedStateDeps:new Set,capturedArtifactDeps:new Set,dependencyVersions:new Map},o=this.buildContext(e,t,r,i,a),c=await this.runWithRetries(e,o,a.dependencyVersions);if(this.commitResult(s,t,n,c,a),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(a.cleanupFunctions,i),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${i}"`)}}}buildContext(e,r,s,i,a){const o=e.key,c="transient"===r.scope,{cleanupFunctions:h,disposeFunctions:d,capturedStateDeps:u,capturedArtifactDeps:l,dependencyVersions:p}=a,g=async e=>{if(e===o)throw new t(`Artifact "${i}" depends on itself.`,"system");const r=this.graph.wouldCreateCycle(o,e);if(r)throw new t(`Adding dependency "${String(e)}" to "${i}" would create a cycle: ${r.join(" -> ")}`,"system");l.add(e);const n=await this.build(e,s),a=this.cache.get(e);return a&&p.set(e,a.version),n},y="singleton"===r.scope?r.controller.signal:m,f=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 a=new Proxy((()=>{}),{get:(s,a)=>{if("symbol"==typeof a||"then"===a)return;if("valueOf"===a||"toString"===a)throw new Error("Cannot perform logic, arithmetic, or string operations inside a selector.");if(n.includes(a))throw new Error(`Array method .${a}() is not allowed in selectors.`);const o=e?`${e}${t}${a}`:a;return e&&r.delete(e),r.add(o),i(o)},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,a),a};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=>u.add(e))),e(this.store.get(!0)));return{state:()=>this.store.get(!0),previous:r.instance,signal:y,onCleanup:e=>h.push(e),onDispose:e=>d.push(e),use:e=>e({resolve:g,require:f,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(o),await this.processStream(i))}))},a={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(a);t&&s.cleanupFunctions.push(t)}catch(e){await n(void 0,e),await this.invalidate(o,!1,!0)}}}}}async runWithRetries(e,r,i){const n=r.signal,a=(e.retries??0)+1;let o=0;for(;o<a;)try{if(n.aborted)throw new s;const c=e.factory(r);let h;if(h=c instanceof Promise?e.timeout?await w(c,e.timeout):await c:c,n.aborted)throw new s;const d=this.detectStaleness(i);if(d){if(o++,i.clear(),o<a)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 s)throw new s;if(e instanceof t)throw e;if(o++,o>=a)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:a,capturedArtifactDeps:o,capturedStateDeps:c}=i;r||(this.updateDependencyGraph(e,o,c),t.cleanupFunctions=n,t.disposeFunctions=a),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 i=this.cache.get(e);i&&"singleton"===i.scope&&await i.invalidationSerializer.do((async()=>{i.version++,await this.cache.invalidateInstance(e),await this.cascadeInvalidation(this.graph.iterDependents(e));const n=this.registry.get(e),a=n&&(t||!n.lazy||this.observer.hasWatchers(e))&&!r;a&&await this.build(e).catch((t=>{t instanceof s||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(a||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 d({retry:!0,throws:!0}),streamOnce:new d({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 a=this.dependencies.get(n);if(a)for(const e of a)s.has(e)||(s.add(e),i.set(e,n),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const i=this.dependents.get(t);if(i)for(const t of i){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,i=new Set,n=[e];i.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)i.has(e)||(i.add(e),s.add(e),n.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear()}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,S=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()}},_=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 f;if(r.package)return r.package;const s=e,i=p(r.cleanupFunctions,s),n="singleton"!==r.scope||void 0!==r.instance,a={instance:r.instance,error:r.error,ready:n,[e]:r.instance,cleanup:i,invalidate:t};return r.package=a,a}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 d({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 d({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;watchers=new Map;watch(e,t=6e4){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,r=6e4){const s=this.registry.get(e);if(!s.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);const i=s.paramKey(t);return this.watchForKey(i,s,r,t)}watchForKey(e,t,r,s){const i="transient"===t.scope,n=i?y(e):e,a=this.watchers.get(n);if(a)return a.observer;const o=new l((async()=>{!i&&void 0===s||this.registry.hasString(e)||this.registry.setVirtual(e,{key:e,factory:i?t.factory:e=>t.factory({...e,params:s}),scope:i?"singleton":t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})}),(async()=>{i||void 0!==s?(await this.registry.unregister(n).catch((()=>{})),this.cache.delete(n),this.watchers.delete(n)):this.cache.invalidatePackage(n),this.listeners.delete(n)}),{gracePeriod:i&&void 0===s?"sync":r});let c;const h={id:n,get count(){return o.subscribers},get:(e=!1)=>0!==o.subscribers||e?this.cache.package(n,((e,t)=>this.container.invalidate(n,e,t))):f,resolve:()=>c||(c=(async()=>{await o.acquire();try{return await this.container.resolve(n)}finally{o.release(),c=void 0}})(),c),subscribe:(e,t=!0)=>{const r=()=>e(h.get());return o.acquire().then((()=>{this.container.resolve(n).then((()=>{this.listeners.has(n)||this.listeners.set(n,new Set),t&&r(),this.listeners.get(n).add(r)}))})).catch((e=>{console.error(`[ArtifactObserver] Resolution failed for "${n}":`,e),this.listeners.get(n)?.add(r)})),()=>{this.listeners.get(n)?.delete(r),o.release()}}};return this.watchers.set(n,{resource:o,observer:h}),h}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 i,this.cache=new _,this.graph=new S,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=t,s=this.registry.get(r),i=this.cache.get(r);if(!s)return;let n="idle";i&&("singleton"===i.scope&&void 0!==i.debounceTimer?n="debouncing":"singleton"===i.scope&&i.buildOnce.running()?n="building":i.error?n="error":void 0!==i.instance&&(n="active")),e.push({id:r,scope:s.scope??"singleton",status:n,dependencies:this.graph.getDependencies(r).map((e=>String(e))),dependents:this.graph.getDependents(r).map((e=>String(e))),stateDependencies:"singleton"===i?.scope?Array.from(i.stateDependencies):[],buildCount:i?.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,t){const r=void 0!==t?this.computeParamKey(e,t):e;await this.manager.dispose(r),await this.registry.unregister(r),this.observer.evictWatcher(r)}async resolve(e,t){return void 0===t?this.resolveStatic(e):this.resolveParameterized(e,t)}async require(e,t){const r=await this.resolve(e,t);if(r.error)throw r.error;return r.instance}watch(e,t,r){return void 0===t?this.observer.watch(e,r):this.observer.watchParameterized(e,t,r)}peek(e,t){const r=void 0!==t?this.computeParamKey(e,t):e;return this.cache.get(r)?.instance}async invalidate(e,t){const r=t?.params,s=t?.replace??!1,i=void 0!==r?this.computeParamKey(e,r):e;return this.manager.invalidate(i,s)}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()}resolveStatic(e){if(!this.registry.has(e))throw new r(e);return this.manager.build(e)}async resolveParameterized(e,s){if(!this.registry.has(e))throw new r(String(e));const i=this.registry.get(e);if(!i.paramKey)throw new t(`Artifact "${String(e)}" is not parameterized.`,"external");const n=i.paramKey(s),a=this.registry.getByString(n);if(a&&!a.paramKey&&!a.virtual)throw new t(`Parameterized artifact "${String(e)}" with params ${JSON.stringify(s)} resolves to key "${n}" which is already registered as a static artifact.`,"system");return this.registry.hasString(n)||this.registry.setVirtual(n,{key:n,factory:e=>i.factory({...e,params:s}),scope:i.scope,lazy:i.lazy,timeout:i.timeout,retries:i.retries,debounce:i.debounce,virtual:!0}),this.manager.build(n)}computeParamKey(e,t){const r=this.registry.get(e);if(!r.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);return r.paramKey(t)}},exports.ArtifactScopes=e;
|
|
1
|
+
"use strict";var e=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},t=class extends e{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},r=class extends e{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},s=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 r;const s=new Promise((e=>r=e));if(this.waiters.push(r),null==e)return void await s;let i;await Promise.race([s.then((()=>clearTimeout(i))),new Promise(((s,n)=>{i=setTimeout((()=>{const e=this.waiters.indexOf(r);-1!==e&&this.waiters.splice(e,1),n(new t("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}},i=class{mutex=new s({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,r,s="Operation timed out"){if(null==r)return e;let i;return Promise.race([e.then((e=>(clearTimeout(i),e))),new Promise(((e,n)=>{i=setTimeout((()=>n(new t(s))),r)}))])}},n=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new s({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new r};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let s,i=null;try{if(this._done)throw new r;i=await e(),this._lastValue=i,this._lastError=void 0,this._hasRun=!0}catch(e){s=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:i,error:s}}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()}},a=class{constructor(e,t,r={}){this.factory=e,this.onCleanup=t,this.options=r}_count=0;init=new i({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 o(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 c(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 h(e){return`${e}__watched`}var d=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function u(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 l=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 d;if(r.package)return r.package;const s=e,i=o(r.cleanupFunctions,s),n="singleton"!==r.scope||void 0!==r.instance,a={instance:r.instance,error:r.error,ready:n,[e]:r.instance,cleanup:i,invalidate:t};return r.package=a,a}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 i({retry:!0,throws:!0}),t||(r.streamSerializer=new n,r.controller=new AbortController)),await c(r.cleanupFunctions,s),await c(r.disposeFunctions,s),r.cleanupFunctions=[],r.disposeFunctions=[],"singleton"===r.scope&&(r.buildOnce=new i({retry:!0,throws:!0})),r.instance=void 0,r.error=void 0}},p=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)??g}setDependencies(e,t){this.registerNode(e);const r=this.dependencies.get(e),s=new Set(t);for(const t of r)s.has(t)||this.removeDependency(e,t);for(const t of s)r.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const r=[t],s=new Set([t]),i=new Map;for(;r.length>0;){const n=r.shift();if(n===e){const r=[];let s=e;for(;void 0!==s&&(r.push(s),s!==t);)s=i.get(s);return r.reverse(),r.unshift(e),r}const a=this.dependencies.get(n);if(a)for(const e of a)s.has(e)||(s.add(e),i.set(e,n),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const i=this.dependents.get(t);if(i)for(const t of i){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,i=new Set,n=[e];i.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)i.has(e)||(i.add(e),s.add(e),n.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},g=new Set,f=class{graph;constructor(){this.graph=new p}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()}},y=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];var w=class e extends Error{category;constructor(t,r,s){super(t,{cause:s}),this.name="ArtifactError",this.category=r,Object.setPrototypeOf(this,e.prototype)}},m=class extends w{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system"),this.name="ArtifactNotFoundError"}},v=class extends w{constructor(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},b=(new AbortController).signal,k=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,t){const r=this.cache.get(e);if("singleton"===r?.scope&&r.buildOnce.done())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const s=this.registry.getByString(e);if(!s)throw new m(e);const i=t??[];if(i.includes(e))throw new w(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${[...i,e].join(" -> ")}`,"system");i.push(e);let n=r;n||(n=this.createCachedArtifact(s),this.cache.set(e,n));try{if("transient"===n.scope)return this.executeBuild(s,n,i);const r=n;try{await r.buildOnce.do((()=>this.executeBuild(s,r,i)))}catch(r){if(r instanceof v)return this.build(e,t);throw r}return r.stream&&r.streamOnce.do(r.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r)))}finally{i.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 a={cleanupFunctions:[],disposeFunctions:[],capturedArtifactDeps:new Set,capturedStateSelectors:[],dependencyVersions:new Map},c=this.buildContext(e,t,r,i,a),h=await this.runWithRetries(e,c,a.dependencyVersions);if(this.commitResult(s,t,n,h,a),n){const e=h.ok?h.value:void 0;return{instance:e,error:h.ok?void 0:h.error,ready:h.ok,[s]:e,cleanup:o(a.cleanupFunctions,i),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${i}"`)}}}buildContext(e,t,r,s,i){const n=e.key,a="transient"===t.scope,{cleanupFunctions:o,disposeFunctions:c,capturedArtifactDeps:h,dependencyVersions:d,capturedStateSelectors:u}=i,l=async(e,t)=>{const i=t?this.computeParamKey(e,t):e;if(i===n)throw new w(`Artifact "${s}" depends on itself.`,"system");const a=this.graph.wouldCreateCycle(n,i);if(a)throw new w(`Adding dependency "${String(i)}" to "${s}" would create a cycle: ${a.join(" -> ")}`,"system");h.add(i);const o=await(t?this.resolveParameterized(e,t):this.build(e,r)),c=this.cache.get(i);return c&&d.set(i,c.version),o},p="singleton"===t.scope?t.controller.signal:b,g=async(e,t)=>{const r=await l(e,t);if(r.error)throw r.error;return r.instance},f=(e,t)=>{const r=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(y.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);return u.push({paths:r,options:t}),e(this.store.get(!0))};return{state:()=>this.store.get(!0),previous:t.instance,signal:p,onCleanup:e=>o.push(e),onDispose:e=>c.push(e),use:e=>e({resolve:l,require:g,select:f}),stream:e=>{if(a)throw new w(`[ArtifactManager] Illegal stream on transient artifact "${s}"`,"system");const r=t,i=async(e,t=void 0)=>{await r.streamSerializer.do((async()=>{void 0!==r.stream&&(r.instance=e,r.error=t,r.version++,this.cache.invalidatePackage(n),await this.processStream(s))}))},o={value:()=>r.instance,get signal(){return r.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>i(e)};r.stream=async()=>{try{const t=await e(o);t&&r.cleanupFunctions.push(t)}catch(e){await i(void 0,e),await this.invalidate(n,!1,!0)}}}}}async runWithRetries(e,t,r){const s=t.signal,i=(e.retries??0)+1;let n=0;for(;n<i;)try{if(s.aborted)throw new v;const a=e.factory(t);let o;if(o=a instanceof Promise?e.timeout?await u(a,e.timeout):await a:a,s.aborted)throw new v;const c=this.detectStaleness(r);if(c){if(n++,r.clear(),n<i)continue;return{ok:!1,error:new w(`Build stale after all retries: dependency "${String(c)}" changed during build.`,"system")}}return{ok:!0,value:o}}catch(e){if(s.aborted||e instanceof v)throw new v;if(e instanceof w)throw e;if(n++,n>=i)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:a,capturedArtifactDeps:o,capturedStateSelectors:c}=i;r||(this.updateDependencyGraph(e,o,c),t.cleanupFunctions=n,t.disposeFunctions=a),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 i=this.registry.get(e),n=i&&(t||!i.lazy||this.observer.hasWatchers(e))&&!r;n&&await this.build(e).catch((t=>{t instanceof v||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(n||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)return;this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateDependencies=new Set;for(const{paths:e}of r)for(const t of e)s.stateDependencies.add(t);if(s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),0===r.length)return;const i=()=>this.invalidate(e),n=new Map;for(const{paths:e,options:t}of r){const r=void 0===t?"undefined":JSON.stringify(t);let s=n.get(r);s||(s={options:t,paths:new Set},n.set(r,s));for(const t of e)s.paths.add(t)}const a=[];for(const{options:e,paths:t}of n.values()){if(0===t.size)continue;const r=Array.from(t);void 0===e?a.push(this.store.watch(r,i)):a.push(this.store.watch(r,i,e))}0===a.length?s.stateUnsubscribe=void 0:1===a.length?s.stateUnsubscribe=a[0]:s.stateUnsubscribe=()=>{for(const e of a)e()}}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 i({retry:!0,throws:!0}),streamOnce:new i({retry:!0,throws:!0}),streamSerializer:new n({yieldMode:"microtask"}),invalidationSerializer:new n({yieldMode:"macrotask"})}}resolveStatic(e){if(!this.registry.has(e))throw new m(e);return this.build(e)}async resolveParameterized(e,t){if(!this.registry.has(e))throw new m(String(e));const r=this.registry.get(e);if(!r.paramKey)throw new w(`Artifact "${String(e)}" is not parameterized.`,"external");const s=r.paramKey(t),i=this.registry.getByString(s);if(i&&!i.paramKey&&!i.virtual)throw new w(`Parameterized artifact "${String(e)}" with params ${JSON.stringify(t)} resolves to key "${s}" which is already registered as a static artifact.`,"system");return this.registry.hasString(s)||this.registry.setVirtual(s,{key:s,factory:e=>r.factory({...e,params:t}),scope:r.scope,lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce,virtual:!0}),this.build(s)}computeParamKey(e,t){const r=this.registry.get(e);if(!r.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);return r.paramKey(t)}},S=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watchers=new Map;watch(e,t=6e4){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,r=6e4){const s=this.registry.get(e);if(!s.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);const i=s.paramKey(t);return this.watchForKey(i,s,r,t)}watchForKey(e,t,r,s){const i="transient"===t.scope,n=i?h(e):e,o=this.watchers.get(n);if(o)return o.observer;const c=new a((async()=>{!i&&void 0===s||this.registry.hasString(e)||this.registry.setVirtual(e,{key:e,factory:i?t.factory:e=>t.factory({...e,params:s}),scope:i?"singleton":t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})}),(async()=>{i||void 0!==s?(await this.registry.unregister(n).catch((()=>{})),this.cache.delete(n),this.watchers.delete(n)):this.cache.invalidatePackage(n),this.listeners.delete(n)}),{gracePeriod:i&&void 0===s?"sync":r});let u;const l={id:n,get count(){return c.subscribers},get:(e=!1)=>0!==c.subscribers||e?this.cache.package(n,((e,t)=>this.container.invalidate(n,e,t))):d,resolve:()=>u||(u=(async()=>{await c.acquire();try{return await this.container.resolve(n)}finally{c.release(),u=void 0}})(),u),subscribe:(e,t=!0)=>{const r=()=>e(l.get());return c.acquire().then((()=>{this.container.resolve(n).then((()=>{this.listeners.has(n)||this.listeners.set(n,new Set),t&&r(),this.listeners.get(n).add(r)}))})).catch((e=>{console.error(`[ArtifactObserver] Resolution failed for "${n}":`,e),this.listeners.get(n)?.add(r)})),()=>{this.listeners.get(n)?.delete(r),c.release()}}};return this.watchers.set(n,{resource:c,observer:l}),l}evictWatcher(e){[e,h(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(h(e))}getWatcherCount(e){const t=this.watchers.get(e)||this.watchers.get(h(e));return t?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}},_=(e=>(e.Singleton="singleton",e.Transient="transient",e))(_||{}),C=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...s}){const{scope:i,...n}=s,a={key:e,factory:t,scope:s.scope??"singleton",lazy:void 0===r||r,...n};return this.artifacts.set(e,a),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw new m(String(e));return this.artifacts.get(e)}getByString(e){return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}hasString(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()}};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 C,this.cache=new l,this.graph=new f,this.observer=new S(this.registry,this.cache,this),this.manager=new k(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const r=t,s=this.registry.get(r),i=this.cache.get(r);if(!s)return;let n="idle";i&&("singleton"===i.scope&&void 0!==i.debounceTimer?n="debouncing":"singleton"===i.scope&&i.buildOnce.running()?n="building":i.error?n="error":void 0!==i.instance&&(n="active")),e.push({id:r,scope:s.scope??"singleton",status:n,dependencies:this.graph.getDependencies(r).map((e=>String(e))),dependents:this.graph.getDependents(r).map((e=>String(e))),stateDependencies:"singleton"===i?.scope?Array.from(i.stateDependencies):[],buildCount:i?.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,t){const r=void 0!==t?this.manager.computeParamKey(e,t):e;await this.manager.dispose(r),await this.registry.unregister(r),this.observer.evictWatcher(r)}async resolve(e,t){return void 0===t?this.manager.resolveStatic(e):this.manager.resolveParameterized(e,t)}async require(e,t){const r=await this.resolve(e,t);if(r.error)throw r.error;return r.instance}watch(e,t,r){return void 0===t?this.observer.watch(e,r):this.observer.watchParameterized(e,t,r)}peek(e,t){const r=void 0!==t?this.manager.computeParamKey(e,t):e;return this.cache.get(r)?.instance}async invalidate(e,t){const r=t?.params,s=t?.replace??!1,i=void 0!==r?this.manager.computeParamKey(e,r):e;return this.manager.invalidate(i,s)}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=_;
|
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(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},i=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...s}){const{scope:i,...n}=s,a={key:e,factory:t,scope:s.scope??"singleton",lazy:void 0===r||r,...n};return this.artifacts.set(e,a),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw new r(String(e));return this.artifacts.get(e)}getByString(e){return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}hasString(e){return this.artifacts.has(e)}async unregister(e){this.artifacts.has(e)&&this.artifacts.delete(e)}size(){return this.artifacts.size}keys(){return Array.from(this.artifacts.keys())}clear(){this.artifacts.clear()}},n=["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)}},o=class extends a{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},c=class extends a{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},h=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 o("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}},d=class{mutex=new h({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 o(r))),t)}))])}},u=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new h({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new c};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new c;s=await e(),this._lastValue=s,this._lastError=void 0,this._hasRun=!0}catch(e){r=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:s,error:r}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},l=class{constructor(e,t,r={}){this.factory=e,this.onCleanup=t,this.options=r}_count=0;init=new d({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 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 y(e){return`${e}__watched`}var f=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function w(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,i){const n=this.cache.get(e);if("singleton"===n?.scope&&n.buildOnce.done())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const a=this.registry.getByString(e);if(!a)throw new r(e);const o=i??[];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 c=n;c||(c=this.createCachedArtifact(a),this.cache.set(e,c));try{if("transient"===c.scope)return this.executeBuild(a,c,o);const t=c;try{await t.buildOnce.do((()=>this.executeBuild(a,t,o)))}catch(t){if(t instanceof s)return this.build(e,i);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 a={cleanupFunctions:[],disposeFunctions:[],capturedStateDeps:new Set,capturedArtifactDeps:new Set,dependencyVersions:new Map},o=this.buildContext(e,t,r,i,a),c=await this.runWithRetries(e,o,a.dependencyVersions);if(this.commitResult(s,t,n,c,a),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(a.cleanupFunctions,i),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${i}"`)}}}buildContext(e,r,s,i,a){const o=e.key,c="transient"===r.scope,{cleanupFunctions:h,disposeFunctions:d,capturedStateDeps:u,capturedArtifactDeps:l,dependencyVersions:p}=a,g=async e=>{if(e===o)throw new t(`Artifact "${i}" depends on itself.`,"system");const r=this.graph.wouldCreateCycle(o,e);if(r)throw new t(`Adding dependency "${String(e)}" to "${i}" would create a cycle: ${r.join(" -> ")}`,"system");l.add(e);const n=await this.build(e,s),a=this.cache.get(e);return a&&p.set(e,a.version),n},y="singleton"===r.scope?r.controller.signal:m,f=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 a=new Proxy((()=>{}),{get:(s,a)=>{if("symbol"==typeof a||"then"===a)return;if("valueOf"===a||"toString"===a)throw new Error("Cannot perform logic, arithmetic, or string operations inside a selector.");if(n.includes(a))throw new Error(`Array method .${a}() is not allowed in selectors.`);const o=e?`${e}${t}${a}`:a;return e&&r.delete(e),r.add(o),i(o)},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,a),a};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=>u.add(e))),e(this.store.get(!0)));return{state:()=>this.store.get(!0),previous:r.instance,signal:y,onCleanup:e=>h.push(e),onDispose:e=>d.push(e),use:e=>e({resolve:g,require:f,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(o),await this.processStream(i))}))},a={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(a);t&&s.cleanupFunctions.push(t)}catch(e){await n(void 0,e),await this.invalidate(o,!1,!0)}}}}}async runWithRetries(e,r,i){const n=r.signal,a=(e.retries??0)+1;let o=0;for(;o<a;)try{if(n.aborted)throw new s;const c=e.factory(r);let h;if(h=c instanceof Promise?e.timeout?await w(c,e.timeout):await c:c,n.aborted)throw new s;const d=this.detectStaleness(i);if(d){if(o++,i.clear(),o<a)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 s)throw new s;if(e instanceof t)throw e;if(o++,o>=a)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:a,capturedArtifactDeps:o,capturedStateDeps:c}=i;r||(this.updateDependencyGraph(e,o,c),t.cleanupFunctions=n,t.disposeFunctions=a),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 i=this.cache.get(e);i&&"singleton"===i.scope&&await i.invalidationSerializer.do((async()=>{i.version++,await this.cache.invalidateInstance(e),await this.cascadeInvalidation(this.graph.iterDependents(e));const n=this.registry.get(e),a=n&&(t||!n.lazy||this.observer.hasWatchers(e))&&!r;a&&await this.build(e).catch((t=>{t instanceof s||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(a||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 d({retry:!0,throws:!0}),streamOnce:new d({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 a=this.dependencies.get(n);if(a)for(const e of a)s.has(e)||(s.add(e),i.set(e,n),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const i=this.dependents.get(t);if(i)for(const t of i){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,i=new Set,n=[e];i.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)i.has(e)||(i.add(e),s.add(e),n.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear()}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,S=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()}},_=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 f;if(r.package)return r.package;const s=e,i=p(r.cleanupFunctions,s),n="singleton"!==r.scope||void 0!==r.instance,a={instance:r.instance,error:r.error,ready:n,[e]:r.instance,cleanup:i,invalidate:t};return r.package=a,a}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 d({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 d({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;watchers=new Map;watch(e,t=6e4){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,r=6e4){const s=this.registry.get(e);if(!s.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);const i=s.paramKey(t);return this.watchForKey(i,s,r,t)}watchForKey(e,t,r,s){const i="transient"===t.scope,n=i?y(e):e,a=this.watchers.get(n);if(a)return a.observer;const o=new l((async()=>{!i&&void 0===s||this.registry.hasString(e)||this.registry.setVirtual(e,{key:e,factory:i?t.factory:e=>t.factory({...e,params:s}),scope:i?"singleton":t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})}),(async()=>{i||void 0!==s?(await this.registry.unregister(n).catch((()=>{})),this.cache.delete(n),this.watchers.delete(n)):this.cache.invalidatePackage(n),this.listeners.delete(n)}),{gracePeriod:i&&void 0===s?"sync":r});let c;const h={id:n,get count(){return o.subscribers},get:(e=!1)=>0!==o.subscribers||e?this.cache.package(n,((e,t)=>this.container.invalidate(n,e,t))):f,resolve:()=>c||(c=(async()=>{await o.acquire();try{return await this.container.resolve(n)}finally{o.release(),c=void 0}})(),c),subscribe:(e,t=!0)=>{const r=()=>e(h.get());return o.acquire().then((()=>{this.container.resolve(n).then((()=>{this.listeners.has(n)||this.listeners.set(n,new Set),t&&r(),this.listeners.get(n).add(r)}))})).catch((e=>{console.error(`[ArtifactObserver] Resolution failed for "${n}":`,e),this.listeners.get(n)?.add(r)})),()=>{this.listeners.get(n)?.delete(r),o.release()}}};return this.watchers.set(n,{resource:o,observer:h}),h}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()}},x=class{registry;cache;graph;manager;observer;store;constructor(e){this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t)},this.registry=new i,this.cache=new _,this.graph=new S,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=t,s=this.registry.get(r),i=this.cache.get(r);if(!s)return;let n="idle";i&&("singleton"===i.scope&&void 0!==i.debounceTimer?n="debouncing":"singleton"===i.scope&&i.buildOnce.running()?n="building":i.error?n="error":void 0!==i.instance&&(n="active")),e.push({id:r,scope:s.scope??"singleton",status:n,dependencies:this.graph.getDependencies(r).map((e=>String(e))),dependents:this.graph.getDependents(r).map((e=>String(e))),stateDependencies:"singleton"===i?.scope?Array.from(i.stateDependencies):[],buildCount:i?.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,t){const r=void 0!==t?this.computeParamKey(e,t):e;await this.manager.dispose(r),await this.registry.unregister(r),this.observer.evictWatcher(r)}async resolve(e,t){return void 0===t?this.resolveStatic(e):this.resolveParameterized(e,t)}async require(e,t){const r=await this.resolve(e,t);if(r.error)throw r.error;return r.instance}watch(e,t,r){return void 0===t?this.observer.watch(e,r):this.observer.watchParameterized(e,t,r)}peek(e,t){const r=void 0!==t?this.computeParamKey(e,t):e;return this.cache.get(r)?.instance}async invalidate(e,t){const r=t?.params,s=t?.replace??!1,i=void 0!==r?this.computeParamKey(e,r):e;return this.manager.invalidate(i,s)}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()}resolveStatic(e){if(!this.registry.has(e))throw new r(e);return this.manager.build(e)}async resolveParameterized(e,s){if(!this.registry.has(e))throw new r(String(e));const i=this.registry.get(e);if(!i.paramKey)throw new t(`Artifact "${String(e)}" is not parameterized.`,"external");const n=i.paramKey(s),a=this.registry.getByString(n);if(a&&!a.paramKey&&!a.virtual)throw new t(`Parameterized artifact "${String(e)}" with params ${JSON.stringify(s)} resolves to key "${n}" which is already registered as a static artifact.`,"system");return this.registry.hasString(n)||this.registry.setVirtual(n,{key:n,factory:e=>i.factory({...e,params:s}),scope:i.scope,lazy:i.lazy,timeout:i.timeout,retries:i.retries,debounce:i.debounce,virtual:!0}),this.manager.build(n)}computeParamKey(e,t){const r=this.registry.get(e);if(!r.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);return r.paramKey(t)}};export{x as ArtifactContainer,e as ArtifactScopes};
|
|
1
|
+
var e=class e extends Error{constructor(t,r){super(t,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},t=class extends e{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},r=class extends e{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},s=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 r;const s=new Promise((e=>r=e));if(this.waiters.push(r),null==e)return void await s;let i;await Promise.race([s.then((()=>clearTimeout(i))),new Promise(((s,n)=>{i=setTimeout((()=>{const e=this.waiters.indexOf(r);-1!==e&&this.waiters.splice(e,1),n(new t("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}},i=class{mutex=new s({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,r,s="Operation timed out"){if(null==r)return e;let i;return Promise.race([e.then((e=>(clearTimeout(i),e))),new Promise(((e,n)=>{i=setTimeout((()=>n(new t(s))),r)}))])}},n=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new s({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new r};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let s,i=null;try{if(this._done)throw new r;i=await e(),this._lastValue=i,this._lastError=void 0,this._hasRun=!0}catch(e){s=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:i,error:s}}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()}},a=class{constructor(e,t,r={}){this.factory=e,this.onCleanup=t,this.options=r}_count=0;init=new i({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 o(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 c(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 h(e){return`${e}__watched`}var d=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function u(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 l=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 d;if(r.package)return r.package;const s=e,i=o(r.cleanupFunctions,s),n="singleton"!==r.scope||void 0!==r.instance,a={instance:r.instance,error:r.error,ready:n,[e]:r.instance,cleanup:i,invalidate:t};return r.package=a,a}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 i({retry:!0,throws:!0}),t||(r.streamSerializer=new n,r.controller=new AbortController)),await c(r.cleanupFunctions,s),await c(r.disposeFunctions,s),r.cleanupFunctions=[],r.disposeFunctions=[],"singleton"===r.scope&&(r.buildOnce=new i({retry:!0,throws:!0})),r.instance=void 0,r.error=void 0}},p=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)??g}setDependencies(e,t){this.registerNode(e);const r=this.dependencies.get(e),s=new Set(t);for(const t of r)s.has(t)||this.removeDependency(e,t);for(const t of s)r.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const r=[t],s=new Set([t]),i=new Map;for(;r.length>0;){const n=r.shift();if(n===e){const r=[];let s=e;for(;void 0!==s&&(r.push(s),s!==t);)s=i.get(s);return r.reverse(),r.unshift(e),r}const a=this.dependencies.get(n);if(a)for(const e of a)s.has(e)||(s.add(e),i.set(e,n),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const i=this.dependents.get(t);if(i)for(const t of i){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,i=new Set,n=[e];i.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)i.has(e)||(i.add(e),s.add(e),n.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},g=new Set,f=class{graph;constructor(){this.graph=new p}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()}},y=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];var w=class e extends Error{category;constructor(t,r,s){super(t,{cause:s}),this.name="ArtifactError",this.category=r,Object.setPrototypeOf(this,e.prototype)}},m=class extends w{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system"),this.name="ArtifactNotFoundError"}},v=class extends w{constructor(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},b=(new AbortController).signal,k=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,t){const r=this.cache.get(e);if("singleton"===r?.scope&&r.buildOnce.done())return this.cache.package(e,((t,r)=>this.invalidate(e,t,r)));const s=this.registry.getByString(e);if(!s)throw new m(e);const i=t??[];if(i.includes(e))throw new w(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${[...i,e].join(" -> ")}`,"system");i.push(e);let n=r;n||(n=this.createCachedArtifact(s),this.cache.set(e,n));try{if("transient"===n.scope)return this.executeBuild(s,n,i);const r=n;try{await r.buildOnce.do((()=>this.executeBuild(s,r,i)))}catch(r){if(r instanceof v)return this.build(e,t);throw r}return r.stream&&r.streamOnce.do(r.stream),this.cache.package(e,((t,r)=>this.invalidate(e,t,r)))}finally{i.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 a={cleanupFunctions:[],disposeFunctions:[],capturedArtifactDeps:new Set,capturedStateSelectors:[],dependencyVersions:new Map},c=this.buildContext(e,t,r,i,a),h=await this.runWithRetries(e,c,a.dependencyVersions);if(this.commitResult(s,t,n,h,a),n){const e=h.ok?h.value:void 0;return{instance:e,error:h.ok?void 0:h.error,ready:h.ok,[s]:e,cleanup:o(a.cleanupFunctions,i),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${i}"`)}}}buildContext(e,t,r,s,i){const n=e.key,a="transient"===t.scope,{cleanupFunctions:o,disposeFunctions:c,capturedArtifactDeps:h,dependencyVersions:d,capturedStateSelectors:u}=i,l=async(e,t)=>{const i=t?this.computeParamKey(e,t):e;if(i===n)throw new w(`Artifact "${s}" depends on itself.`,"system");const a=this.graph.wouldCreateCycle(n,i);if(a)throw new w(`Adding dependency "${String(i)}" to "${s}" would create a cycle: ${a.join(" -> ")}`,"system");h.add(i);const o=await(t?this.resolveParameterized(e,t):this.build(e,r)),c=this.cache.get(i);return c&&d.set(i,c.version),o},p="singleton"===t.scope?t.controller.signal:b,g=async(e,t)=>{const r=await l(e,t);if(r.error)throw r.error;return r.instance},f=(e,t)=>{const r=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(y.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);return u.push({paths:r,options:t}),e(this.store.get(!0))};return{state:()=>this.store.get(!0),previous:t.instance,signal:p,onCleanup:e=>o.push(e),onDispose:e=>c.push(e),use:e=>e({resolve:l,require:g,select:f}),stream:e=>{if(a)throw new w(`[ArtifactManager] Illegal stream on transient artifact "${s}"`,"system");const r=t,i=async(e,t=void 0)=>{await r.streamSerializer.do((async()=>{void 0!==r.stream&&(r.instance=e,r.error=t,r.version++,this.cache.invalidatePackage(n),await this.processStream(s))}))},o={value:()=>r.instance,get signal(){return r.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>i(e)};r.stream=async()=>{try{const t=await e(o);t&&r.cleanupFunctions.push(t)}catch(e){await i(void 0,e),await this.invalidate(n,!1,!0)}}}}}async runWithRetries(e,t,r){const s=t.signal,i=(e.retries??0)+1;let n=0;for(;n<i;)try{if(s.aborted)throw new v;const a=e.factory(t);let o;if(o=a instanceof Promise?e.timeout?await u(a,e.timeout):await a:a,s.aborted)throw new v;const c=this.detectStaleness(r);if(c){if(n++,r.clear(),n<i)continue;return{ok:!1,error:new w(`Build stale after all retries: dependency "${String(c)}" changed during build.`,"system")}}return{ok:!0,value:o}}catch(e){if(s.aborted||e instanceof v)throw new v;if(e instanceof w)throw e;if(n++,n>=i)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:a,capturedArtifactDeps:o,capturedStateSelectors:c}=i;r||(this.updateDependencyGraph(e,o,c),t.cleanupFunctions=n,t.disposeFunctions=a),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 i=this.registry.get(e),n=i&&(t||!i.lazy||this.observer.hasWatchers(e))&&!r;n&&await this.build(e).catch((t=>{t instanceof v||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(n||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)return;this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateDependencies=new Set;for(const{paths:e}of r)for(const t of e)s.stateDependencies.add(t);if(s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),0===r.length)return;const i=()=>this.invalidate(e),n=new Map;for(const{paths:e,options:t}of r){const r=void 0===t?"undefined":JSON.stringify(t);let s=n.get(r);s||(s={options:t,paths:new Set},n.set(r,s));for(const t of e)s.paths.add(t)}const a=[];for(const{options:e,paths:t}of n.values()){if(0===t.size)continue;const r=Array.from(t);void 0===e?a.push(this.store.watch(r,i)):a.push(this.store.watch(r,i,e))}0===a.length?s.stateUnsubscribe=void 0:1===a.length?s.stateUnsubscribe=a[0]:s.stateUnsubscribe=()=>{for(const e of a)e()}}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 i({retry:!0,throws:!0}),streamOnce:new i({retry:!0,throws:!0}),streamSerializer:new n({yieldMode:"microtask"}),invalidationSerializer:new n({yieldMode:"macrotask"})}}resolveStatic(e){if(!this.registry.has(e))throw new m(e);return this.build(e)}async resolveParameterized(e,t){if(!this.registry.has(e))throw new m(String(e));const r=this.registry.get(e);if(!r.paramKey)throw new w(`Artifact "${String(e)}" is not parameterized.`,"external");const s=r.paramKey(t),i=this.registry.getByString(s);if(i&&!i.paramKey&&!i.virtual)throw new w(`Parameterized artifact "${String(e)}" with params ${JSON.stringify(t)} resolves to key "${s}" which is already registered as a static artifact.`,"system");return this.registry.hasString(s)||this.registry.setVirtual(s,{key:s,factory:e=>r.factory({...e,params:t}),scope:r.scope,lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce,virtual:!0}),this.build(s)}computeParamKey(e,t){const r=this.registry.get(e);if(!r.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);return r.paramKey(t)}},S=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watchers=new Map;watch(e,t=6e4){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,r=6e4){const s=this.registry.get(e);if(!s.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);const i=s.paramKey(t);return this.watchForKey(i,s,r,t)}watchForKey(e,t,r,s){const i="transient"===t.scope,n=i?h(e):e,o=this.watchers.get(n);if(o)return o.observer;const c=new a((async()=>{!i&&void 0===s||this.registry.hasString(e)||this.registry.setVirtual(e,{key:e,factory:i?t.factory:e=>t.factory({...e,params:s}),scope:i?"singleton":t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})}),(async()=>{i||void 0!==s?(await this.registry.unregister(n).catch((()=>{})),this.cache.delete(n),this.watchers.delete(n)):this.cache.invalidatePackage(n),this.listeners.delete(n)}),{gracePeriod:i&&void 0===s?"sync":r});let u;const l={id:n,get count(){return c.subscribers},get:(e=!1)=>0!==c.subscribers||e?this.cache.package(n,((e,t)=>this.container.invalidate(n,e,t))):d,resolve:()=>u||(u=(async()=>{await c.acquire();try{return await this.container.resolve(n)}finally{c.release(),u=void 0}})(),u),subscribe:(e,t=!0)=>{const r=()=>e(l.get());return c.acquire().then((()=>{this.container.resolve(n).then((()=>{this.listeners.has(n)||this.listeners.set(n,new Set),t&&r(),this.listeners.get(n).add(r)}))})).catch((e=>{console.error(`[ArtifactObserver] Resolution failed for "${n}":`,e),this.listeners.get(n)?.add(r)})),()=>{this.listeners.get(n)?.delete(r),c.release()}}};return this.watchers.set(n,{resource:c,observer:l}),l}evictWatcher(e){[e,h(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(h(e))}getWatcherCount(e){const t=this.watchers.get(e)||this.watchers.get(h(e));return t?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}},_=(e=>(e.Singleton="singleton",e.Transient="transient",e))(_||{}),C=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...s}){const{scope:i,...n}=s,a={key:e,factory:t,scope:s.scope??"singleton",lazy:void 0===r||r,...n};return this.artifacts.set(e,a),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw new m(String(e));return this.artifacts.get(e)}getByString(e){return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}hasString(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()}},x=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 C,this.cache=new l,this.graph=new f,this.observer=new S(this.registry,this.cache,this),this.manager=new k(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const r=t,s=this.registry.get(r),i=this.cache.get(r);if(!s)return;let n="idle";i&&("singleton"===i.scope&&void 0!==i.debounceTimer?n="debouncing":"singleton"===i.scope&&i.buildOnce.running()?n="building":i.error?n="error":void 0!==i.instance&&(n="active")),e.push({id:r,scope:s.scope??"singleton",status:n,dependencies:this.graph.getDependencies(r).map((e=>String(e))),dependents:this.graph.getDependents(r).map((e=>String(e))),stateDependencies:"singleton"===i?.scope?Array.from(i.stateDependencies):[],buildCount:i?.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,t){const r=void 0!==t?this.manager.computeParamKey(e,t):e;await this.manager.dispose(r),await this.registry.unregister(r),this.observer.evictWatcher(r)}async resolve(e,t){return void 0===t?this.manager.resolveStatic(e):this.manager.resolveParameterized(e,t)}async require(e,t){const r=await this.resolve(e,t);if(r.error)throw r.error;return r.instance}watch(e,t,r){return void 0===t?this.observer.watch(e,r):this.observer.watchParameterized(e,t,r)}peek(e,t){const r=void 0!==t?this.manager.computeParamKey(e,t):e;return this.cache.get(r)?.instance}async invalidate(e,t){const r=t?.params,s=t?.replace??!1,i=void 0!==r?this.manager.computeParamKey(e,r):e;return this.manager.invalidate(i,s)}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{x as ArtifactContainer,_ as ArtifactScopes};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asaidimu/utils-artifacts",
|
|
3
|
-
"version": "8.2.
|
|
3
|
+
"version": "8.2.3",
|
|
4
4
|
"description": "Reactive artifact container.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@asaidimu/utils-events": "1.
|
|
9
|
+
"@asaidimu/utils-events": "^1.0.0"
|
|
10
10
|
},
|
|
11
11
|
"keywords": [
|
|
12
12
|
"typescript",
|