@asaidimu/utils-artifacts 8.2.12 → 8.2.14

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.ts CHANGED
@@ -1,243 +1,8 @@
1
+ import { DataStore, StateUpdater, SubscribeOptions } from "@asaidimu/utils-store";
1
2
  import { Issue, Severity, SystemError, SystemError as SystemError$1 } from "@asaidimu/utils-error";
2
- import { SubscribeOptions, SubscribeOptions as SubscribeOptions$1 } from "@asaidimu/utils-events";
3
+ import { EventBus } from "@asaidimu/utils-events";
3
4
  import { SystemLogger } from "@asaidimu/utils-logger";
4
- import { EventBus } from "@asaidimu/utils-events/types";
5
5
 
6
- //#region src/store/types.d.ts
7
- /**
8
- * Utility type for representing partial updates to the state, allowing deep nesting.
9
- * It makes all properties optional and applies the same transformation recursively
10
- * to nested objects, allowing for selective updates while
11
- * preserving the original structure. It also includes the original type T and
12
- * undefined as possibilities for the top level and nested values.
13
- */
14
- type DeepPartial<T> = T extends object ? T extends readonly (infer U)[] ? readonly (DeepPartial<U> | undefined)[] | undefined | T : T extends (infer U)[] ? (DeepPartial<U> | undefined)[] | undefined | T : { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> | undefined : T[K] | undefined } | undefined | T : T | undefined | symbol;
15
- /**
16
- * Extended store state for monitoring the current execution status (e.g., if an update is in progress).
17
- */
18
- interface StoreExecutionState<T> {
19
- /** Indicates if a state update process is currently executing. */
20
- executing: boolean;
21
- /** The changes (DeepPartial) currently being processed in the execution cycle. Null if none. */
22
- changes: DeepPartial<T> | null;
23
- /** A queue of pending state update functions/objects to be applied sequentially. */
24
- pendingChanges: Array<StateUpdater<T>>;
25
- /** Names of all currently registered middlewares. */
26
- middlewares: string[];
27
- /** Details of the middleware currently running. Null if none. */
28
- runningMiddleware: {
29
- id: string;
30
- name: string;
31
- startTime: number;
32
- } | null;
33
- /** Indicates if the store is currently within an active transaction block. */
34
- transactionActive: boolean;
35
- }
36
- /**
37
- * Event types emitted by the state store for observability and debugging.
38
- */
39
- type StoreEvent = "update:start" | "update:complete" | "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" | "transaction:start" | "transaction:complete" | "transaction:error" | "persistence:ready" | "persistence:queued" | "persistence:success" | "persistence:retry" | "persistence:failed" | "persistence:queue_cleared" | "persistence:init_error" | "action:start" | "action:complete" | "action:error" | "selector:accessed" | "selector:changed";
40
- /**
41
- * Represents a state update, which can be:
42
- * 1. The full new state (`T`).
43
- * 2. A partial update object (`DeepPartial<T>`).
44
- * 3. A function that receives the current state and returns a partial update (sync or async).
45
- */
46
- type StateUpdater<T> = T | DeepPartial<T> | ((state: T) => DeepPartial<T> | Promise<DeepPartial<T>>);
47
- /**
48
- * Core types for the reactive data store
49
- */
50
- /**
51
- * Type for a Transform Middleware function.
52
- * It modifies (transforms) the incoming changes and must return a `DeepPartial<T>`.
53
- */
54
- type TransformMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<DeepPartial<T>> | DeepPartial<T>;
55
- /**
56
- * Type for a Blocking Middleware function.
57
- * It determines whether the state update should proceed or be blocked.
58
- * It returns a boolean or an object containing a `block` boolean and an optional `error`.
59
- */
60
- type BlockingMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<boolean | {
61
- block: boolean;
62
- error?: Error;
63
- }> | boolean | {
64
- block: boolean;
65
- error?: Error;
66
- };
67
- /**
68
- * Type representing the configuration object passed to the `use` method to register a middleware.
69
- */
70
- interface MiddlewareConfig<T> {
71
- /** The middleware function (can be a transform or blocking middleware). */
72
- action: TransformMiddleware<T> | BlockingMiddleware<T>;
73
- /** An optional, human-readable name for the middleware. */
74
- name?: string;
75
- /** If true, the middleware is treated as a blocking middleware (must return a boolean or `{ block: boolean }`). */
76
- block?: boolean;
77
- }
78
- /**
79
- * Interface for a reactive selector result, providing access to the value and subscription capabilities.
80
- */
81
- interface ReactiveSelector<S> {
82
- /** Unique identifier for the selector. */
83
- id: string;
84
- /** Function to get the current computed value of the selector. */
85
- get: () => S;
86
- /**
87
- * Subscribes a callback function to run whenever the selector's result changes.
88
- * Returns an unsubscribe function.
89
- */
90
- subscribe: (callback: (state: S) => void) => () => void;
91
- }
92
- interface ActionWatcher {
93
- /** Unique identifier for the action */
94
- name: string;
95
- /** Function to get the current computed value of the action. */
96
- status: () => boolean;
97
- /**
98
- * Subscribes a callback function to run whenever the action's status changes.
99
- * Returns an unsubscribe function.
100
- */
101
- subscribe: (callback: () => void) => () => void;
102
- }
103
- interface TransactionOptions {
104
- /** If true, blocks resolution until changes are fully committed to the database row */
105
- flush?: boolean;
106
- }
107
- /**
108
- * Interface defining the contract for the core data state store.
109
- * T must be an object type.
110
- */
111
- interface DataStore<T extends object> {
112
- /**
113
- * Gets the current state of the store.
114
- * @param clone If true, returns a deep clone of the state; otherwise, returns the internal state reference.
115
- * @returns The current state T.
116
- */
117
- get(clone?: boolean): T;
118
- /**
119
- * Gets a subset of the store.
120
- * @param paths The paths which to include in the returned object.
121
- * @param separator Optional separator for paths. Defaults to `.` .
122
- * @returns An object of the shape K mapping paths to their current values.
123
- */
124
- subset<K extends Record<string, any> = Record<string, any>>(paths: Array<string>, separator?: string): K;
125
- /**
126
- * Registers a named action function that can modify the state.
127
- * @param action The action configuration object.
128
- * @returns A function to unregister the action.
129
- */
130
- register<R extends any[]>(action: {
131
- name: string;
132
- fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
133
- debounce?: {
134
- delay: number;
135
- condition?: (previous: R, current: R) => boolean;
136
- };
137
- }): () => void;
138
- /**
139
- * Executes (dispatches) a previously registered action by its name.
140
- * @param name The name of the action.
141
- * @param args The parameters to pass to the action function.
142
- * @returns A promise that resolves to the final state after the action and subsequent updates are complete.
143
- */
144
- dispatch<R extends any[]>(name: string, ...args: R): Promise<T>;
145
- /**
146
- * Sets or updates the state using a StateUpdater.
147
- * @param update The new state, partial state, or a function returning a partial state.
148
- * @param options Configuration options for the set operation.
149
- * @returns A promise that resolves to the current state when the update is complete.
150
- */
151
- set(update: StateUpdater<T>, options?: {
152
- force?: boolean;
153
- actionId?: string;
154
- }): Promise<T>;
155
- /**
156
- * Creates a reactive selector that computes a derived value and tracks dependencies.
157
- * @param selector A function to compute the derived state value S from the full state T.
158
- * @returns A `ReactiveSelector<S>` object.
159
- */
160
- select<S>(selector: (state: T) => S): ReactiveSelector<S>;
161
- /**
162
- * Subscribes a callback to run when the data at the specified path(s) changes.
163
- * @param path A single path string or an array of path strings to watch.
164
- * @param callback The function to execute when a change occurs in the watched path(s).
165
- * @param options Extra options to pass to the event bus
166
- * @returns An unsubscribe function.
167
- */
168
- watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
169
- /**
170
- * Subscribes to execution‑status changes of a registered action.
171
- *
172
- * The provided callback is called **every time** the action transitions
173
- * between idle and running (i.e. on `action:start`, `action:complete`, or
174
- * `action:error` for the given name). The current status can also be read
175
- * synchronously with `isActionRunning(name)`.
176
- *
177
- * **Deferred listener teardown**
178
- * To avoid unnecessary churn when subscriptions are rapidly created and
179
- * destroyed, the underlying event listeners are not removed immediately
180
- * on unsubscribe. Instead, a *pending reset* is queued via `queueMicrotask`.
181
- * If a new subscription for the same action arrives before that microtask
182
- * executes, the reset is silently cancelled and the already‑established
183
- * listeners are reused. This keeps the subscription infrastructure stable
184
- * and prevents cascading notifications that could otherwise arise from
185
- * repeated subscribe‑unsubscribe‑subscribe cycles.
186
- *
187
- * @param name - The name of the action to watch.
188
- * @returns An ActionWatcher
189
- */
190
- watchAction(name: string): ActionWatcher;
191
- /**
192
- * Executes an operation function within a transaction block.
193
- * All state updates (`set` or actions) within the transaction are batched and applied atomically (all or nothing).
194
- * @param operation The function containing the state updates.
195
- * @returns A promise that resolves to the return value of the operation function.
196
- */
197
- transaction<R>(operation: () => R | Promise<R>, options?: TransactionOptions): Promise<R>;
198
- /**
199
- * Registers a middleware function to intercept state updates.
200
- * @param props The middleware configuration.
201
- * @returns A function to unregister the middleware.
202
- */
203
- use(props: MiddlewareConfig<T>): () => boolean;
204
- /**
205
- * Subscribes a listener to a specific store event type.
206
- * @param event The type of store event to listen for.
207
- * @param listener The callback function to execute when the event fires.
208
- * @returns An unsubscribe function.
209
- */
210
- on(event: StoreEvent, listener: (data: any) => void): () => void;
211
- /**
212
- * Returns the unique identifier of the store instance.
213
- */
214
- id(): string;
215
- /**
216
- * Checks whether the store is fully initialized and ready for use.
217
- */
218
- isReady(): boolean;
219
- /**
220
- * Returns a promise that resolves once the store is fully initialised.
221
- * Safe to call multiple times — all callers share the same latch.
222
- *
223
- * @param timeout - Optional maximum wait time in milliseconds.
224
- * @throws {TimeoutError} If the store does not become ready within the timeout.
225
- *
226
- * @example
227
- * await store.ready();
228
- * const state = store.get();
229
- */
230
- ready(timeout?: number): Promise<void>;
231
- /**
232
- * Returns a readonly snapshot of the current execution state of the store.
233
- */
234
- state(): Readonly<StoreExecutionState<T>>;
235
- /**
236
- * Releases all resources held by the store and renders it unusable
237
- */
238
- dispose(): Promise<void>;
239
- }
240
- //#endregion
241
6
  //#region src/artifacts/types.d.ts
242
7
  /**
243
8
  * Defines the lifecycle and sharing strategy for an artifact.
@@ -326,7 +91,7 @@ interface UseDependencyContext<TRegistry extends Record<string, any>, TState ext
326
91
  * @param selector A function that takes the full state and returns a slice of state.
327
92
  * @returns The selected slice of state.
328
93
  */
329
- select<S>(selector: (state: TState) => S, options?: SubscribeOptions$1): S;
94
+ select<S>(selector: (state: TState) => S, options?: SubscribeOptions): S;
330
95
  }
331
96
  /**
332
97
  * Context object provided to an artifact stream producer function (`ctx.stream` callback).
@@ -683,7 +448,7 @@ type InferRegistry<T extends Record<string, {
683
448
  */
684
449
  interface StateGroup {
685
450
  paths: string[];
686
- options?: SubscribeOptions$1;
451
+ options?: SubscribeOptions;
687
452
  }
688
453
  interface ExportedArtifact {
689
454
  key: string;
@@ -691,7 +456,7 @@ interface ExportedArtifact {
691
456
  state: {
692
457
  groups: Array<{
693
458
  paths: string[];
694
- options?: SubscribeOptions$1;
459
+ options?: SubscribeOptions;
695
460
  }>;
696
461
  hash: string;
697
462
  };
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@asaidimu/utils-error"),t=require("@asaidimu/utils-events"),n=require("@asaidimu/utils-logger");var r=class t extends e.SystemError{constructor(e,n){super({code:`SYNC_ERROR`,message:e,cause:n}),this.name=`SyncError`,Object.setPrototypeOf(this,t.prototype)}},i=class e extends r{constructor(t){super(`[ArtifactContainer] Operation timed out: ${t}`),this.name=`TimeoutError`,Object.setPrototypeOf(this,e.prototype)}},a=class e extends r{constructor(t){super(`[Serializer] The serializer has been marked as done!`,t),this.name=`SerializerExecutionDone`,Object.setPrototypeOf(this,e.prototype)}},o=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){this._locked=!0;return}if(this.waiters.length>=this._capacity)throw Error(`Mutex queue is full (capacity: ${this._capacity})`);let t,n=new Promise(e=>t=e);if(this.waiters.push(t),e==null){await n;return}let r;await Promise.race([n.then(()=>clearTimeout(r)),new Promise((n,a)=>{r=setTimeout(()=>{let e=this.waiters.indexOf(t);e!==-1&&this.waiters.splice(e,1),a(new i(`Mutex lock timed out`))},e)})])}tryLock(){return this._locked?!1:(this._locked=!0,!0)}unlock(){if(!this._locked)throw Error(`Mutex is not locked`);let e=this.waiters.shift();e?this._yieldMode===`microtask`?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},s=class{mutex=new o({yieldMode:`microtask`});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=!!e,this.throws=!!t}resolve(e){if(this._done)throw Error(`Cannot resolve: operation is already completed.`);if(this.running())throw Error(`Cannot resolve: operation is currently running.`);this._value=e,this._done=!0}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){let e=Error(`Cannot execute doSync while an async operation is pending.`);if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){let e=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()}let e=Error(`Cannot execute doSync while an async operation is pending.`);if(this.throws)throw e;return{value:null,error:e}}try{let 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 this.promise!==null&&!this.done()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw Error(`Once operation is not yet complete`);if(this._error)throw this._error;return this._value}reset(){if(this.running())throw 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,n=`Operation timed out`){if(t==null)return e;let r;return Promise.race([e.then(e=>(clearTimeout(r),e)),new Promise((e,a)=>{r=setTimeout(()=>a(new i(n)),t)})])}},c=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new o({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??`macrotask`})}async do(e,t){if(this._done)return{value:null,error:new a};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let n=null,r;try{if(this._done)throw new a;n=await e(),this._lastValue=n,this._lastError=void 0,this._hasRun=!0}catch(e){r=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:n,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{factory;onCleanup;options;_count=0;init=new s({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;constructor(e,t,n={}){this.factory=e,this.onCleanup=t,this.options=n}get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;let e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){if(this._count<=0){console.warn(`SharedResource.release() called, but count is already 0.`);return}this._count--,this._count===0&&this.scheduleCleanup()}peek(){let e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,this.cleanupTimer!==void 0&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){let e=this.options.gracePeriod??`microtask`;if(e===`sync`){this.executeCleanup();return}if(e===`microtask`){this.pendingMicrotask=!0,queueMicrotask(()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())});return}this.cleanupTimer=setTimeout(()=>{this.cleanupTimer=void 0,!(this._count>0)&&this.executeCleanup()},e)}executeCleanup(){let 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 u(e,t){if(!e.length)return;let n=e.slice(),r=t?`[${t}]`:`[ArtifactCleanup]`;return async()=>{for(let e=n.length-1;e>=0;e--)try{await n[e]()}catch(t){console.error(`${r} Cleanup error at index ${e}:`,t)}}}async function d(e,t){let n=t?`[${t}]`:`[ArtifactCleanup]`;for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${n} Cleanup error at index ${t}:`,e)}}function f(e){return`${e}__watched`}const p=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function m(e,t){let n,r=new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Timeout: ${t}ms`)),t)});try{return Promise.race([e,r])}finally{clearTimeout(n)}}async function h(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}var g=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,n){let r=this.get(e);if(!r)return p;if(r.package)return r.package;let i=e,a=u(r.cleanupFunctions,i),o=r.scope===`singleton`?r.instance!==void 0:!0,s={instance:r.instance,error:r.error,ready:o,[n||e]:r.instance,cleanup:a,invalidate:t};return r.package=s,s}invalidatePackage(e){let t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(e,t=!1){let n=this.get(e);if(!n)return;let r=e;n.scope===`singleton`&&(n.stateUnsubscribe&&=(n.stateUnsubscribe(),void 0),n.debounceTimer&&=(clearTimeout(n.debounceTimer),void 0),n.controller.abort(),await n.streamOnce.current(),n.streamSerializer.close(),n.stream=void 0,n.streamOnce=new s({retry:!0,throws:!0}),t||(n.streamSerializer=new c,n.controller=new AbortController)),await d(n.cleanupFunctions,r),await d(n.disposeFunctions,r),n.cleanupFunctions=[],n.disposeFunctions=[],n.scope===`singleton`&&(n.buildOnce=new s({retry:!0,throws:!0})),n.instance=void 0,n.error=void 0}},_=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;let t=this.dependencies.get(e);if(t)for(let n of t)this.dependents.get(n)?.delete(e);let n=this.dependents.get(e);if(n)for(let t of n)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){let t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){let t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??v}setDependencies(e,t){this.registerNode(e);let n=this.dependencies.get(e),r=new Set(t);for(let t of n)r.has(t)||this.removeDependency(e,t);for(let t of r)n.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];let n=[t],r=new Set([t]),i=new Map;for(;n.length>0;){let a=n.shift();if(a===e){let n=[],r=e;for(;r!==void 0&&(n.push(r),r!==t);)r=i.get(r);return n.reverse(),n.unshift(e),n}let o=this.dependencies.get(a);if(o)for(let e of o)r.has(e)||(r.add(e),i.set(e,a),n.push(e))}return null}topologicalSort(){let e=new Map,t=Array.from(this.dependencies.keys());for(let n of t)e.set(n,this.dependencies.get(n)?.size??0);let n=[];for(let[t,r]of e)r===0&&n.push(t);let r=[];for(;n.length>0;){let t=n.shift();r.push(t);let i=this.dependents.get(t);if(i)for(let t of i){let r=(e.get(t)||0)-1;e.set(t,r),r===0&&n.push(t)}}if(r.length!==t.length)throw Error(`Cycle detected in graph; topological sort impossible.`);return r}getTransitiveDependencies(e,t=!1){return this.bfs(e,`dependencies`,t)}getTransitiveDependents(e,t=!1){return this.bfs(e,`dependents`,t)}bfs(e,t,n){let r=new Set,i=new Set,a=[e];i.add(e),n&&r.add(e);let o=t===`dependencies`?this.dependencies:this.dependents;for(;a.length>0;){let e=a.shift(),t=o.get(e);if(t)for(let e of t)i.has(e)||(i.add(e),r.add(e),a.push(e))}return r}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])=>{let n=Array.from(t).join(`, `);return`${String(e)} → [${n||`∅`}]`}).join(`
2
- `)}};const v=new Set;var y=class{graph;constructor(){this.graph=new _}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){let n=Array.from(t).map(e=>e);this.graph.setDependencies(e,n)}wouldCreateCycle(e,t,n){if(n?.has(t)){let e=Array.from(n),r=e.indexOf(t),i=e.slice(r);return i.push(t),i}return this.graph.wouldCreateCycle(e,t)||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()}};const b=[`map`,`filter`,`reduce`,`forEach`,`find`,`findIndex`,`some`,`every`,`includes`,`flatMap`,`flat`,`slice`,`splice`];function x(e,t=`.`){let n=new Set,r=new Map,i=(e=``)=>{if(r.has(e))return r.get(e);let a=new Proxy(()=>{},{get:(r,a)=>{if(typeof a==`symbol`||a===`then`)return;if(a===`valueOf`||a===`toString`)throw Error(`Cannot perform logic, arithmetic, or string operations inside a selector.`);if(b.includes(a))throw Error(`Array method .${a}() is not allowed in selectors.`);let o=e?`${e}${t}${a}`:a;return e&&n.delete(e),n.add(o),i(o)},has:()=>{throw Error(`The 'in' operator is not allowed in selectors.`)},apply:()=>{throw Error(`Selectors cannot call functions or methods.`)}});return r.set(e,a),a};try{e(i())}catch(e){throw Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(n)}const S={NOT_FOUND:e.CommonErrors.NOT_FOUND,DUPLICATE_KEY:e.CommonErrors.DUPLICATE_KEY,INVALID_COMMAND:e.CommonErrors.INVALID_COMMAND,INTERNAL_ERROR:e.CommonErrors.INTERNAL_ERROR,CONCURRENCY_ERROR:e.CommonErrors.CONCURRENCY_ERROR},C=`[ArtifactContainer]`;function w(t){return new e.SystemError({code:S.NOT_FOUND,message:`${C} Artifact "${t}" not found.`,operation:`artifact:resolve`})}function T(t){return new e.SystemError({code:S.INTERNAL_ERROR,message:`${C} Cycle detected: ${t.join(` -> `)}`,operation:`artifact:resolve`})}function E(t){return new e.SystemError({code:S.INVALID_COMMAND,message:`${C} ${t}`,operation:`artifact:build`})}function D(t){return new e.SystemError({code:S.INTERNAL_ERROR,message:`${C} Artifact with key:${t} has already been disposed`,operation:`artifact:watch`})}function O(t){return new e.SystemError({code:S.CONCURRENCY_ERROR,message:`${C} Operation timed out: ${t}`,operation:`artifact:build`})}function k(t){return new e.SystemError({code:S.DUPLICATE_KEY,message:`${C} An artifact with key:"${t}" already exists!`,operation:`artifact:register`})}function A(t){return new e.SystemError({code:S.INVALID_COMMAND,message:`${C} Artifact "${t}" is not parameterized.`,operation:`artifact:resolve`})}function j(t,n){return new e.SystemError({code:S.DUPLICATE_KEY,message:`${C} Parameterized artifact "${t}" with params resolves to key "${n}" which is already registered as a static artifact.`,operation:`artifact:resolve`})}function M(t){return new e.SystemError({code:S.INTERNAL_ERROR,message:`${C} Artifact "${t}" depends on itself.`,operation:`artifact:build`})}function N(t){return new e.SystemError({code:S.CONCURRENCY_ERROR,message:`${C} Build stale after all retries: dependency "${String(t)}" changed during build.`,operation:`artifact:build`})}function P(t){return new e.SystemError({code:S.INVALID_COMMAND,message:t,operation:`artifact:import`})}function F(t){return new e.SystemError({code:S.INTERNAL_ERROR,message:`${C} Artifact "${t}" instance is not JSON-serializable (POJO are required for persistence)`,operation:`artifact:export`})}var I=class extends Error{constructor(){super(`Build superseded by invalidation`),this.name=`SupersededBuildError`}};const L=new AbortController().signal;var R=class{registry;cache;graph;store;observer;logger;events;constructor(e,t,n,r,i,a,o){this.registry=e,this.cache=t,this.graph=n,this.store=r,this.observer=i,this.logger=a,this.events=o}async build(e,t,n){let r=this.cache.get(e);if(r?.scope===`singleton`&&r.buildOnce.done())return this.cache.package(e,(t,n)=>this.invalidate(e,t,n),n);let i=this.registry.getByString(e);if(!i)throw w(e);let a=t??[];if(a.includes(e))throw T([...a,e].map(String));a.push(e);let o=r;o||(o=this.createCachedArtifact(i),this.cache.set(e,o)),this.events?.emit({name:`build:start`,payload:{key:e,templateKey:n}});try{if(o.scope===`transient`)return this.executeBuild(i,o,a);let r=o;try{await r.buildOnce.do(()=>this.executeBuild(i,r,a))}catch(r){if(r instanceof I)return this.build(e,t,n);throw r}return r.stream&&r.streamOnce.do(r.stream),this.events?.emit({name:`build:complete`,payload:{key:e,instance:o.instance}}),this.cache.package(e,(t,n)=>this.invalidate(e,t,n),n)}catch(t){throw t instanceof I||this.events?.emit({name:`build:error`,payload:{key:e,error:t}}),t}finally{a.pop()}}async executeBuild(e,t,n){let r=e.key,i=String(r),a=t.scope===`transient`;t.buildCount++,t.scope===`singleton`&&(t.activeDebounceMs=e.debounce??0);let o={cleanupFunctions:[],disposeFunctions:[],capturedArtifactDeps:new Set,capturedStateSelectors:[],dependencyVersions:new Map},s=this.buildContext(e,t,n,i,o),c=await this.runWithRetries(e,s,o.dependencyVersions);if(this.commitResult(r,t,a,c,o),a){let e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[r]:e,cleanup:u(o.cleanupFunctions,i),invalidate:async()=>this.logger.warn(`Cannot invalidate transient "${i}"`)}}}buildContext(e,t,n,r,i){let a=e.key,o=t.scope===`transient`,{cleanupFunctions:s,disposeFunctions:c,capturedArtifactDeps:l,dependencyVersions:u,capturedStateSelectors:d}=i,f=async(e,t)=>{let i=t?this.computeParamKey(e,t):e;if(i===a)throw M(r);let o=this.graph.wouldCreateCycle(a,i);if(o)throw T(o);l.add(i);let s=await(t?this.resolveParameterized(e,t):this.build(e,n)),c=this.cache.get(i);return c&&u.set(i,c.version),s},p=t.scope===`singleton`?t.controller.signal:L,m=async(e,t)=>{let n=await f(e,t);if(n.error)throw n.error;return n.instance},h=(e,t)=>{let n=x(e);return d.push({paths:n,options:t}),e(this.store.get(!0))};return{state:()=>this.store.get(!0),previous:t.instance,signal:p,onCleanup:e=>s.push(e),onDispose:e=>c.push(e),use:e=>e({resolve:f,require:m,select:h}),stream:e=>{if(o)throw E(`Illegal stream on transient artifact "${r}"`);let n=t,i=async(e,t=void 0)=>{await n.streamSerializer.do(async()=>{n.stream!==void 0&&(n.instance=e,n.error=t,n.version++,this.cache.invalidatePackage(a),await this.processStream(r),this.events?.emit({name:`stream:emit`,payload:{key:r,value:e}}))})},s={value:()=>n.instance,get signal(){return n.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>i(e)};n.stream=async()=>{try{let t=await e(s);t&&n.cleanupFunctions.push(t)}catch(e){await i(void 0,e),await this.invalidate(a,!1,!0)}}}}}async runWithRetries(t,n,r){let i=n.signal,a=(t.retries??0)+1,o=0;for(;o<a;)try{if(i.aborted)throw new I;let e=t.factory(n),s;if(s=e instanceof Promise?t.timeout?await m(e,t.timeout):await e:e,i.aborted)throw new I;let c=this.detectStaleness(r);if(c){if(o++,r.clear(),o<a)continue;return{ok:!1,error:N(String(c))}}return{ok:!0,value:s}}catch(t){if(i.aborted||t instanceof I)throw new I;if(t instanceof e.SystemError)throw t;if(o++,o>=a)return{ok:!1,error:t}}return{ok:!1,error:Error(`Build exhausted retry budget unexpectedly.`)}}commitResult(e,t,n,r,i){let{cleanupFunctions:a,disposeFunctions:o,capturedArtifactDeps:s,capturedStateSelectors:c}=i;n||(this.updateDependencyGraph(e,s,c),t.cleanupFunctions=a,t.disposeFunctions=o,t.artifactDependencies=new Set(s),t.stateGroups=c.map(({paths:e,options:t})=>({paths:e,options:t}))),r.ok?(t.instance=r.value,t.error=void 0):(t.instance=void 0,t.error=r.error),t.version++,this.cache.invalidatePackage(e)}detectStaleness(e){for(let[t,n]of e){let e=this.cache.get(t);if(e&&e.version!==n)return t}return null}async invalidate(e,t=!1,n=!1){let r=this.cache.get(e);if(!r)return;if(r.scope!==`singleton`)return this.executeInvalidation(e,t,n);let i=r;return i.debounceTimer&&=(clearTimeout(i.debounceTimer),void 0),!t&&i.activeDebounceMs>0?new Promise((r,a)=>{i.debounceTimer=setTimeout(()=>{i.debounceTimer=void 0,this.executeInvalidation(e,t,n).then(r).catch(a)},i.activeDebounceMs)}):this.executeInvalidation(e,t,n)}async executeInvalidation(e,t,n=!1){let r=this.cache.get(e);!r||r.scope!==`singleton`||await r.invalidationSerializer.do(async()=>{r.version++,await this.cache.invalidateInstance(e);let i=this.graph.iterDependents(e),a=i.size>0;await this.cascadeInvalidation(i),this.events?.emit({name:`artifact:invalidated`,payload:{key:e,cascade:a,replace:t}});let o=this.registry.get(e),s=o&&(t||!o.lazy||this.observer.hasWatchers(e))&&!n;s&&await this.build(e).catch(t=>{t instanceof I||this.logger.error(`Rebuild failed for "${String(e)}"`,t)}),(s||n)&&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),this.events?.emit({name:`artifact:disposed`,payload:{key:e}}))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(e.size===0)return;let t=[];for(let n of e)t.push(this.invalidate(n).catch(e=>{this.logger.error(`Cascade failed for "${String(n)}"`,e)}));await Promise.all(t)}updateDependencyGraph(e,t,n){let r=this.cache.get(e);if(!r||r.scope!==`singleton`)return;this.graph.registerNode(e),this.graph.setDependencies(e,t),r.stateDependencies=new Set;for(let{paths:e}of n)for(let t of e)r.stateDependencies.add(t);if(r.stateUnsubscribe&&=(r.stateUnsubscribe(),void 0),n.length===0)return;let i=()=>this.invalidate(e),a=new Map;for(let{paths:e,options:t}of n){let n=t===void 0?`undefined`:JSON.stringify(t),r=a.get(n);r||(r={options:t,paths:new Set},a.set(n,r));for(let t of e)r.paths.add(t)}let o=[];for(let{options:e,paths:t}of a.values()){if(t.size===0)continue;let n=Array.from(t);e===void 0?o.push(this.store.watch(n,i)):o.push(this.store.watch(n,i,e))}o.length===0?r.stateUnsubscribe=void 0:o.length===1?r.stateUnsubscribe=o[0]:r.stateUnsubscribe=()=>{for(let e of o)e()}}createCachedArtifact(e){return e.scope===`transient`?{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 s({retry:!0,throws:!0}),streamOnce:new s({retry:!0,throws:!0}),streamSerializer:new c({yieldMode:`microtask`}),invalidationSerializer:new c({yieldMode:`macrotask`}),stateGroups:[],artifactDependencies:new Set}}resolveStatic(e){if(!this.registry.getByString(e))throw w(e);return this.build(e)}async resolveParameterized(e,t){let n=this.registry.getByString(e);if(!n)throw w(String(e));if(!n.paramKey)throw A(String(e));let r=n.paramKey(t),i=this.registry.getByString(r);if(i&&!i.paramKey&&!i.virtual)throw j(String(e),r);return this.registry.hasString(r)||this.registry.setVirtual(r,{key:r,factory:e=>n.factory({...e,params:t}),scope:n.scope,lazy:n.lazy,timeout:n.timeout,retries:n.retries,debounce:n.debounce,virtual:!0}),this.build(r,void 0,e)}computeParamKey(e,t){let n=this.registry.getByString(e);if(!n||!n.paramKey)throw A(String(e));return n.paramKey(t)}},z=class{registry;cache;container;logger;listeners=new Map;watchers=new Map;constructor(e,t,n,r){this.registry=e,this.cache=t,this.container=n,this.logger=r}watch(e,t=60*1e3){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,n=60*1e3){let r=this.registry.get(e);if(!r.paramKey)throw Error(`Artifact "${String(e)}" is not parameterized.`);let i=r.paramKey(t);return this.watchForKey(i,r,n,t)}watchForKey(e,t,n,r){let i=t.scope===`transient`,a=i?f(e):e,o=this.watchers.get(a);if(o)return o.observer;let s=new l(async()=>{(i||r!==void 0)&&!this.registry.hasString(e)&&this.registry.setVirtual(e,{key:e,factory:i?t.factory:e=>t.factory({...e,params:r}),scope:i?`singleton`:t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})},async()=>{i||r!==void 0?(await this.registry.unregister(a).catch(()=>{}),this.cache.delete(a),this.watchers.delete(a)):this.cache.invalidatePackage(a),this.listeners.delete(a)},{gracePeriod:i&&r===void 0?`sync`:n}),c,u={id:a,get count(){return s.subscribers},get:(t=!1)=>s.subscribers===0&&!t?p:this.cache.package(a,(e,t)=>this.container.invalidate(a,e,t),e),resolve:()=>c||(c=(async()=>{await s.acquire();try{return await this.container.resolve(a)}finally{s.release(),c=void 0}})(),c),subscribe:(e,t=!0)=>{let n=()=>e(u.get());return s.acquire().then(()=>{this.container.resolve(a).then(()=>{this.listeners.has(a)||this.listeners.set(a,new Set),t&&n(),this.listeners.get(a).add(n)})}).catch(e=>{this.logger.error(`Resolution failed for "${a}"`,e),this.listeners.get(a)?.add(n)}),()=>{this.listeners.get(a)?.delete(n),s.release()}}};return this.watchers.set(a,{resource:s,observer:u}),u}evictWatcher(e){[e,f(e)].forEach(e=>{let t=this.watchers.get(e);t&&(t.resource.forceCleanup(),this.watchers.delete(e))})}notify(e){let t=this.listeners.get(e);if(!(!t||t.size===0))for(let n of t)try{n()}catch(t){this.logger.error(`Listener error for "${e}"`,t)}}hasWatchers(e){return this.watchers.has(e)||this.watchers.has(f(e))}getWatcherCount(e){return(this.watchers.get(e)||this.watchers.get(f(e)))?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}};let B=function(e){return e.Singleton=`singleton`,e.Transient=`transient`,e}({});var V=class{artifacts=new Map;register({key:e,factory:t,lazy:n,...r}){let{scope:i,...a}=r,o={key:e,factory:t,scope:r.scope??`singleton`,lazy:n===void 0?!0:n,...a};return this.artifacts.set(e,o),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw w(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()}},H=class e{registry;cache;graph;manager;observer;logger;store;events;constructor(e,r){this.logger=r?.logger??new n.Logger([new n.ConsoleSink],{module:`artifacts`}),this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t),subset:(...t)=>e.subset(...t)},this.events=(0,t.createEventBus)({errorHandler:e=>this.logger.error(`Lifecycle event error`,e)}),this.registry=new V,this.cache=new g,this.graph=new y,this.observer=new z(this.registry,this.cache,this,this.logger),this.manager=new R(this.registry,this.cache,this.graph,this.store,this.observer,this.logger,this.events)}debugInfo(){let e=[];return this.registry.keys().forEach(t=>{let n=t,r=this.registry.getByString(n),i=this.cache.get(n);if(!r)return;let a=`idle`;i&&(i.scope===`singleton`&&i.debounceTimer!==void 0?a=`debouncing`:i.scope===`singleton`&&i.buildOnce.running()?a=`building`:i.error?a=`error`:i.instance!==void 0&&(a=`active`)),e.push({id:n,scope:r.scope??`singleton`,status:a,dependencies:this.graph.getDependencies(n).map(e=>String(e)),dependents:this.graph.getDependents(n).map(e=>String(e)),stateDependencies:i?.scope===`singleton`?Array.from(i.stateDependencies):[],buildCount:i?.buildCount??0})}),e}register(e){let{key:t}=e,n=t;this.registry.has(t)&&(this.logger.warn(`Overwriting artifact "${n}".`),this.manager.dispose(t).catch(e=>{this.logger.error(`Failed to dispose existing artifact "${n}"`,e)})),this.registry.register(e),this.graph.registerNode(t);let r=e.scope??`singleton`,i=e.lazy??!0;return this.events.emit({name:`artifact:registered`,payload:{key:n,scope:r}}),!i&&r===`singleton`&&this.resolve(t).catch(e=>{this.logger.error(`Eager load failed for "${n}"`,e)}),()=>this.unregister(t)}has(e){return this.registry.has(e)}async unregister(e,t){let n=t===void 0?e:this.manager.computeParamKey(e,t);await this.manager.dispose(n),await this.registry.unregister(n),this.observer.evictWatcher(n)}async resolve(e,t){return t===void 0?this.manager.resolveStatic(e):this.manager.resolveParameterized(e,t)}async require(e,t){let n=await this.resolve(e,t);if(n.error)throw n.error;return n.instance}watch(e,t,n){return t===void 0?this.observer.watch(e,n):this.observer.watchParameterized(e,t,n)}peek(e,t){let n=t===void 0?e:this.manager.computeParamKey(e,t);return this.cache.get(n)?.instance}async invalidate(e,t){let n=t?.params,r=t?.replace??!1,i=n===void 0?e:this.manager.computeParamKey(e,n);return this.manager.invalidate(i,r)}on(e,t){return this.events.subscribe(e,t)}once(e,t){return this.events.once(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){let e=this.registry.keys();await Promise.allSettled(e.map(e=>this.manager.dispose(e).catch(t=>{this.logger.error(`Failed to dispose artifact "${String(e)}"`,t)}))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear(),this.events.emit({name:`container:dispose`,payload:{}}),this.events.clear({permanent:!0})}async export(){let e=[];for(let t of this.cache.keys()){let n=this.cache.get(t);if(!n||n.scope!==`singleton`||n.instance===void 0)continue;let r=new Set;for(let e of n.stateGroups)for(let t of e.paths)r.add(t);let i=Array.from(r).sort(),a=this.store.subset(i),o=await h(JSON.stringify(a,Object.keys(a).sort())),s;try{s=structuredClone(n.instance)}catch{throw F(t)}e.push({key:t,instance:s,state:{groups:n.stateGroups.map(e=>({paths:e.paths,options:e.options})),hash:o},dependencies:Array.from(n.artifactDependencies)})}let t={version:`1.0`,timestamp:Date.now(),artifacts:e},n=await h(JSON.stringify(t));return{...t,checksum:n}}async restore(e){let{checksum:t,...n}=e;if(await h(JSON.stringify(n))!==t)throw P(`Bundle checksum mismatch – data corrupted`);if(e.version!==`1.0`)throw P(`Unsupported bundle version: ${e.version}`);let r=new Map;for(let t of e.artifacts)r.set(t.key,t);let i=new Set,a=new Map;for(let t of e.artifacts)for(let e of t.dependencies)a.has(e)||a.set(e,new Set),a.get(e).add(t.key);let o=async e=>{let t=new Set;for(let n of e.state.groups)for(let e of n.paths)t.add(e);let n=Array.from(t).sort(),r=this.store.subset(n);return h(JSON.stringify(r,Object.keys(r).sort()))};for(let t of e.artifacts)await o(t)!==t.state.hash&&i.add(t.key);let l=Array.from(i);for(;l.length;){let e=l.shift(),t=a.get(e);if(t)for(let e of t)i.has(e)||(i.add(e),l.push(e))}for(let t of e.artifacts){if(i.has(t.key))continue;this.cache.get(t.key)&&await this.cache.invalidateInstance(t.key,!1);let e={scope:`singleton`,instance:t.instance,error:void 0,version:1,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set(t.state.groups.flatMap(e=>e.paths)),activeDebounceMs:0,buildOnce:new s({retry:!0,throws:!0}),streamSerializer:new c({yieldMode:`microtask`}),invalidationSerializer:new c({yieldMode:`macrotask`}),stateUnsubscribe:void 0,debounceTimer:void 0,controller:new AbortController,streamOnce:new s({retry:!0,throws:!0}),stream:void 0,stateGroups:t.state.groups,artifactDependencies:new Set(t.dependencies)};e.buildOnce.resolve(t.instance),this.cache.set(t.key,e);let n=[];for(let e of t.state.groups){let r=this.store.watch(e.paths,()=>this.invalidate(t.key),e.options);n.push(r)}e.stateUnsubscribe=()=>{for(let e of n)e()},this.graph.setDependencies(t.key,t.dependencies)}}static async from(t){let n=new e(t.store,{logger:t.logger});if(t.bundle){if(typeof t.bundle!=`object`||!t.bundle.version||!Array.isArray(t.bundle.artifacts))throw P(`Invalid bundle: missing version or artifacts array`);await n.restore(t.bundle)}for(let e of t.templates)n.register(e);return n}};exports.ArtifactContainer=H,exports.ArtifactScopes=B,exports.ErrorCodes=S,exports.SupersededBuildError=I,Object.defineProperty(exports,"SystemError",{enumerable:!0,get:function(){return e.SystemError}}),exports.artifactNotFound=w,exports.buildStaleAfterRetries=N,exports.cycleDetected=T,exports.illegalScope=E,exports.invalidExport=F,exports.invalidImport=P,exports.keyConflict=k,exports.notParameterized=A,exports.paramKeyCollision=j,exports.selfDependency=M,exports.timeoutError=O,exports.watcherDisposed=D;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@asaidimu/utils-sync"),t=require("@asaidimu/utils-store"),n=require("@asaidimu/utils-error"),r=require("@asaidimu/utils-events"),i=require("@asaidimu/utils-logger");function a(e,t){if(!e.length)return;let n=e.slice(),r=t?`[${t}]`:`[ArtifactCleanup]`;return async()=>{for(let e=n.length-1;e>=0;e--)try{await n[e]()}catch(t){console.error(`${r} Cleanup error at index ${e}:`,t)}}}async function o(e,t){let n=t?`[${t}]`:`[ArtifactCleanup]`;for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${n} Cleanup error at index ${t}:`,e)}}function s(e){return`${e}__watched`}const c=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function l(e,t){let n,r=new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Timeout: ${t}ms`)),t)});try{return Promise.race([e,r])}finally{clearTimeout(n)}}async function u(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}var d=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,n){let r=this.get(e);if(!r)return c;if(r.package)return r.package;let i=e,o=a(r.cleanupFunctions,i),s=r.scope===`singleton`?r.instance!==void 0:!0,l={instance:r.instance,error:r.error,ready:s,[n||e]:r.instance,cleanup:o,invalidate:t};return r.package=l,l}invalidatePackage(e){let t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(t,n=!1){let r=this.get(t);if(!r)return;let i=t;r.scope===`singleton`&&(r.stateUnsubscribe&&=(r.stateUnsubscribe(),void 0),r.debounceTimer&&=(clearTimeout(r.debounceTimer),void 0),r.controller.abort(),await r.streamOnce.current(),r.streamSerializer.close(),r.stream=void 0,r.streamOnce=new e.Once({retry:!0,throws:!0}),n||(r.streamSerializer=new e.Serializer,r.controller=new AbortController)),await o(r.cleanupFunctions,i),await o(r.disposeFunctions,i),r.cleanupFunctions=[],r.disposeFunctions=[],r.scope===`singleton`&&(r.buildOnce=new e.Once({retry:!0,throws:!0})),r.instance=void 0,r.error=void 0}},f=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;let t=this.dependencies.get(e);if(t)for(let n of t)this.dependents.get(n)?.delete(e);let n=this.dependents.get(e);if(n)for(let t of n)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){let t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){let t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??p}setDependencies(e,t){this.registerNode(e);let n=this.dependencies.get(e),r=new Set(t);for(let t of n)r.has(t)||this.removeDependency(e,t);for(let t of r)n.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];let n=[t],r=new Set([t]),i=new Map;for(;n.length>0;){let a=n.shift();if(a===e){let n=[],r=e;for(;r!==void 0&&(n.push(r),r!==t);)r=i.get(r);return n.reverse(),n.unshift(e),n}let o=this.dependencies.get(a);if(o)for(let e of o)r.has(e)||(r.add(e),i.set(e,a),n.push(e))}return null}topologicalSort(){let e=new Map,t=Array.from(this.dependencies.keys());for(let n of t)e.set(n,this.dependencies.get(n)?.size??0);let n=[];for(let[t,r]of e)r===0&&n.push(t);let r=[];for(;n.length>0;){let t=n.shift();r.push(t);let i=this.dependents.get(t);if(i)for(let t of i){let r=(e.get(t)||0)-1;e.set(t,r),r===0&&n.push(t)}}if(r.length!==t.length)throw Error(`Cycle detected in graph; topological sort impossible.`);return r}getTransitiveDependencies(e,t=!1){return this.bfs(e,`dependencies`,t)}getTransitiveDependents(e,t=!1){return this.bfs(e,`dependents`,t)}bfs(e,t,n){let r=new Set,i=new Set,a=[e];i.add(e),n&&r.add(e);let o=t===`dependencies`?this.dependencies:this.dependents;for(;a.length>0;){let e=a.shift(),t=o.get(e);if(t)for(let e of t)i.has(e)||(i.add(e),r.add(e),a.push(e))}return r}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])=>{let n=Array.from(t).join(`, `);return`${String(e)} → [${n||`∅`}]`}).join(`
2
+ `)}};const p=new Set;var m=class{graph;constructor(){this.graph=new f}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){let n=Array.from(t).map(e=>e);this.graph.setDependencies(e,n)}wouldCreateCycle(e,t,n){if(n?.has(t)){let e=Array.from(n),r=e.indexOf(t),i=e.slice(r);return i.push(t),i}return this.graph.wouldCreateCycle(e,t)||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()}};const h={NOT_FOUND:n.CommonErrors.NOT_FOUND,DUPLICATE_KEY:n.CommonErrors.DUPLICATE_KEY,INVALID_COMMAND:n.CommonErrors.INVALID_COMMAND,INTERNAL_ERROR:n.CommonErrors.INTERNAL_ERROR,CONCURRENCY_ERROR:n.CommonErrors.CONCURRENCY_ERROR},g=`[ArtifactContainer]`;function _(e){return new n.SystemError({code:h.NOT_FOUND,message:`${g} Artifact "${e}" not found.`,operation:`artifact:resolve`})}function v(e){return new n.SystemError({code:h.INTERNAL_ERROR,message:`${g} Cycle detected: ${e.join(` -> `)}`,operation:`artifact:resolve`})}function y(e){return new n.SystemError({code:h.INVALID_COMMAND,message:`${g} ${e}`,operation:`artifact:build`})}function b(e){return new n.SystemError({code:h.INTERNAL_ERROR,message:`${g} Artifact with key:${e} has already been disposed`,operation:`artifact:watch`})}function x(e){return new n.SystemError({code:h.CONCURRENCY_ERROR,message:`${g} Operation timed out: ${e}`,operation:`artifact:build`})}function S(e){return new n.SystemError({code:h.DUPLICATE_KEY,message:`${g} An artifact with key:"${e}" already exists!`,operation:`artifact:register`})}function C(e){return new n.SystemError({code:h.INVALID_COMMAND,message:`${g} Artifact "${e}" is not parameterized.`,operation:`artifact:resolve`})}function w(e,t){return new n.SystemError({code:h.DUPLICATE_KEY,message:`${g} Parameterized artifact "${e}" with params resolves to key "${t}" which is already registered as a static artifact.`,operation:`artifact:resolve`})}function T(e){return new n.SystemError({code:h.INTERNAL_ERROR,message:`${g} Artifact "${e}" depends on itself.`,operation:`artifact:build`})}function E(e){return new n.SystemError({code:h.CONCURRENCY_ERROR,message:`${g} Build stale after all retries: dependency "${String(e)}" changed during build.`,operation:`artifact:build`})}function D(e){return new n.SystemError({code:h.INVALID_COMMAND,message:e,operation:`artifact:import`})}function O(e){return new n.SystemError({code:h.INTERNAL_ERROR,message:`${g} Artifact "${e}" instance is not JSON-serializable (POJO are required for persistence)`,operation:`artifact:export`})}var k=class extends Error{constructor(){super(`Build superseded by invalidation`),this.name=`SupersededBuildError`}};const A=new AbortController().signal;var j=class{registry;cache;graph;store;observer;logger;events;constructor(e,t,n,r,i,a,o){this.registry=e,this.cache=t,this.graph=n,this.store=r,this.observer=i,this.logger=a,this.events=o}async build(e,t,n){let r=this.cache.get(e);if(r?.scope===`singleton`&&r.buildOnce.done())return this.cache.package(e,(t,n)=>this.invalidate(e,t,n),n);let i=this.registry.getByString(e);if(!i)throw _(e);let a=t??[];if(a.includes(e))throw v([...a,e].map(String));a.push(e);let o=r;o||(o=this.createCachedArtifact(i),this.cache.set(e,o)),this.events?.emit({name:`build:start`,payload:{key:e,templateKey:n}});try{if(o.scope===`transient`)return this.executeBuild(i,o,a);let r=o;try{await r.buildOnce.do(()=>this.executeBuild(i,r,a))}catch(r){if(r instanceof k)return this.build(e,t,n);throw r}return r.stream&&r.streamOnce.do(r.stream),this.events?.emit({name:`build:complete`,payload:{key:e,instance:o.instance}}),this.cache.package(e,(t,n)=>this.invalidate(e,t,n),n)}catch(t){throw t instanceof k||this.events?.emit({name:`build:error`,payload:{key:e,error:t}}),t}finally{a.pop()}}async executeBuild(e,t,n){let r=e.key,i=String(r),o=t.scope===`transient`;t.buildCount++,t.scope===`singleton`&&(t.activeDebounceMs=e.debounce??0);let s={cleanupFunctions:[],disposeFunctions:[],capturedArtifactDeps:new Set,capturedStateSelectors:[],dependencyVersions:new Map},c=this.buildContext(e,t,n,i,s),l=await this.runWithRetries(e,c,s.dependencyVersions);if(this.commitResult(r,t,o,l,s),o){let e=l.ok?l.value:void 0;return{instance:e,error:l.ok?void 0:l.error,ready:l.ok,[r]:e,cleanup:a(s.cleanupFunctions,i),invalidate:async()=>this.logger.warn(`Cannot invalidate transient "${i}"`)}}}buildContext(e,n,r,i,a){let o=e.key,s=n.scope===`transient`,{cleanupFunctions:c,disposeFunctions:l,capturedArtifactDeps:u,dependencyVersions:d,capturedStateSelectors:f}=a,p=async(e,t)=>{let n=t?this.computeParamKey(e,t):e;if(n===o)throw T(i);let a=this.graph.wouldCreateCycle(o,n);if(a)throw v(a);u.add(n);let s=await(t?this.resolveParameterized(e,t):this.build(e,r)),c=this.cache.get(n);return c&&d.set(n,c.version),s},m=n.scope===`singleton`?n.controller.signal:A,h=async(e,t)=>{let n=await p(e,t);if(n.error)throw n.error;return n.instance},g=(e,n)=>{let r=(0,t.buildPaths)(e);return f.push({paths:r,options:n}),e(this.store.get(!0))};return{state:()=>this.store.get(!0),previous:n.instance,signal:m,onCleanup:e=>c.push(e),onDispose:e=>l.push(e),use:e=>e({resolve:p,require:h,select:g}),stream:e=>{if(s)throw y(`Illegal stream on transient artifact "${i}"`);let t=n,r=async(e,n=void 0)=>{await t.streamSerializer.do(async()=>{t.stream!==void 0&&(t.instance=e,t.error=n,t.version++,this.cache.invalidatePackage(o),await this.processStream(i),this.events?.emit({name:`stream:emit`,payload:{key:i,value:e}}))})},a={value:()=>t.instance,get signal(){return t.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>r(e)};t.stream=async()=>{try{let n=await e(a);n&&t.cleanupFunctions.push(n)}catch(e){await r(void 0,e),await this.invalidate(o,!1,!0)}}}}}async runWithRetries(e,t,r){let i=t.signal,a=(e.retries??0)+1,o=0;for(;o<a;)try{if(i.aborted)throw new k;let n=e.factory(t),s;if(s=n instanceof Promise?e.timeout?await l(n,e.timeout):await n:n,i.aborted)throw new k;let c=this.detectStaleness(r);if(c){if(o++,r.clear(),o<a)continue;return{ok:!1,error:E(String(c))}}return{ok:!0,value:s}}catch(e){if(i.aborted||e instanceof k)throw new k;if(e instanceof n.SystemError)throw e;if(o++,o>=a)return{ok:!1,error:e}}return{ok:!1,error:Error(`Build exhausted retry budget unexpectedly.`)}}commitResult(e,t,n,r,i){let{cleanupFunctions:a,disposeFunctions:o,capturedArtifactDeps:s,capturedStateSelectors:c}=i;n||(this.updateDependencyGraph(e,s,c),t.cleanupFunctions=a,t.disposeFunctions=o,t.artifactDependencies=new Set(s),t.stateGroups=c.map(({paths:e,options:t})=>({paths:e,options:t}))),r.ok?(t.instance=r.value,t.error=void 0):(t.instance=void 0,t.error=r.error),t.version++,this.cache.invalidatePackage(e)}detectStaleness(e){for(let[t,n]of e){let e=this.cache.get(t);if(e&&e.version!==n)return t}return null}async invalidate(e,t=!1,n=!1){let r=this.cache.get(e);if(!r)return;if(r.scope!==`singleton`)return this.executeInvalidation(e,t,n);let i=r;return i.debounceTimer&&=(clearTimeout(i.debounceTimer),void 0),!t&&i.activeDebounceMs>0?new Promise((r,a)=>{i.debounceTimer=setTimeout(()=>{i.debounceTimer=void 0,this.executeInvalidation(e,t,n).then(r).catch(a)},i.activeDebounceMs)}):this.executeInvalidation(e,t,n)}async executeInvalidation(e,t,n=!1){let r=this.cache.get(e);!r||r.scope!==`singleton`||await r.invalidationSerializer.do(async()=>{r.version++,await this.cache.invalidateInstance(e);let i=this.graph.iterDependents(e),a=i.size>0;await this.cascadeInvalidation(i),this.events?.emit({name:`artifact:invalidated`,payload:{key:e,cascade:a,replace:t}});let o=this.registry.get(e),s=o&&(t||!o.lazy||this.observer.hasWatchers(e))&&!n;s&&await this.build(e).catch(t=>{t instanceof k||this.logger.error(`Rebuild failed for "${String(e)}"`,t)}),(s||n)&&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),this.events?.emit({name:`artifact:disposed`,payload:{key:e}}))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(e.size===0)return;let t=[];for(let n of e)t.push(this.invalidate(n).catch(e=>{this.logger.error(`Cascade failed for "${String(n)}"`,e)}));await Promise.all(t)}updateDependencyGraph(e,t,n){let r=this.cache.get(e);if(!r||r.scope!==`singleton`)return;this.graph.registerNode(e),this.graph.setDependencies(e,t),r.stateDependencies=new Set;for(let{paths:e}of n)for(let t of e)r.stateDependencies.add(t);if(r.stateUnsubscribe&&=(r.stateUnsubscribe(),void 0),n.length===0)return;let i=()=>this.invalidate(e),a=new Map;for(let{paths:e,options:t}of n){let n=t===void 0?`undefined`:JSON.stringify(t),r=a.get(n);r||(r={options:t,paths:new Set},a.set(n,r));for(let t of e)r.paths.add(t)}let o=[];for(let{options:e,paths:t}of a.values()){if(t.size===0)continue;let n=Array.from(t);e===void 0?o.push(this.store.watch(n,i)):o.push(this.store.watch(n,i,e))}o.length===0?r.stateUnsubscribe=void 0:o.length===1?r.stateUnsubscribe=o[0]:r.stateUnsubscribe=()=>{for(let e of o)e()}}createCachedArtifact(t){return t.scope===`transient`?{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:t.debounce?t.debounce:0,controller:new AbortController,buildOnce:new e.Once({retry:!0,throws:!0}),streamOnce:new e.Once({retry:!0,throws:!0}),streamSerializer:new e.Serializer({yieldMode:`microtask`}),invalidationSerializer:new e.Serializer({yieldMode:`macrotask`}),stateGroups:[],artifactDependencies:new Set}}resolveStatic(e){if(!this.registry.getByString(e))throw _(e);return this.build(e)}async resolveParameterized(e,t){let n=this.registry.getByString(e);if(!n)throw _(String(e));if(!n.paramKey)throw C(String(e));let r=n.paramKey(t),i=this.registry.getByString(r);if(i&&!i.paramKey&&!i.virtual)throw w(String(e),r);return this.registry.hasString(r)||this.registry.setVirtual(r,{key:r,factory:e=>n.factory({...e,params:t}),scope:n.scope,lazy:n.lazy,timeout:n.timeout,retries:n.retries,debounce:n.debounce,virtual:!0}),this.build(r,void 0,e)}computeParamKey(e,t){let n=this.registry.getByString(e);if(!n||!n.paramKey)throw C(String(e));return n.paramKey(t)}},M=class{registry;cache;container;logger;listeners=new Map;watchers=new Map;constructor(e,t,n,r){this.registry=e,this.cache=t,this.container=n,this.logger=r}watch(e,t=60*1e3){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,n=60*1e3){let r=this.registry.get(e);if(!r.paramKey)throw Error(`Artifact "${String(e)}" is not parameterized.`);let i=r.paramKey(t);return this.watchForKey(i,r,n,t)}watchForKey(t,n,r,i){let a=n.scope===`transient`,o=a?s(t):t,l=this.watchers.get(o);if(l)return l.observer;let u=new e.SharedResource(async()=>{(a||i!==void 0)&&!this.registry.hasString(t)&&this.registry.setVirtual(t,{key:t,factory:a?n.factory:e=>n.factory({...e,params:i}),scope:a?`singleton`:n.scope,lazy:n.lazy,timeout:n.timeout,retries:n.retries,debounce:n.debounce,paramKey:n.paramKey,virtual:!0})},async()=>{a||i!==void 0?(await this.registry.unregister(o).catch(()=>{}),this.cache.delete(o),this.watchers.delete(o)):this.cache.invalidatePackage(o),this.listeners.delete(o)},{gracePeriod:a&&i===void 0?`sync`:r}),d,f={id:o,get count(){return u.subscribers},get:(e=!1)=>u.subscribers===0&&!e?c:this.cache.package(o,(e,t)=>this.container.invalidate(o,e,t),t),resolve:()=>d||(d=(async()=>{await u.acquire();try{return await this.container.resolve(o)}finally{u.release(),d=void 0}})(),d),subscribe:(e,t=!0)=>{let n=()=>e(f.get());return u.acquire().then(()=>{this.container.resolve(o).then(()=>{this.listeners.has(o)||this.listeners.set(o,new Set),t&&n(),this.listeners.get(o).add(n)})}).catch(e=>{this.logger.error(`Resolution failed for "${o}"`,e),this.listeners.get(o)?.add(n)}),()=>{this.listeners.get(o)?.delete(n),u.release()}}};return this.watchers.set(o,{resource:u,observer:f}),f}evictWatcher(e){[e,s(e)].forEach(e=>{let t=this.watchers.get(e);t&&(t.resource.forceCleanup(),this.watchers.delete(e))})}notify(e){let t=this.listeners.get(e);if(!(!t||t.size===0))for(let n of t)try{n()}catch(t){this.logger.error(`Listener error for "${e}"`,t)}}hasWatchers(e){return this.watchers.has(e)||this.watchers.has(s(e))}getWatcherCount(e){return(this.watchers.get(e)||this.watchers.get(s(e)))?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}};let N=function(e){return e.Singleton=`singleton`,e.Transient=`transient`,e}({});var P=class{artifacts=new Map;register({key:e,factory:t,lazy:n,...r}){let{scope:i,...a}=r,o={key:e,factory:t,scope:r.scope??`singleton`,lazy:n===void 0?!0:n,...a};return this.artifacts.set(e,o),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw _(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()}},F=class t{registry;cache;graph;manager;observer;logger;store;events;constructor(e,t){this.logger=t?.logger??new i.Logger([new i.ConsoleSink],{module:`artifacts`}),this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t),subset:(...t)=>e.subset(...t)},this.events=(0,r.createEventBus)({errorHandler:e=>this.logger.error(`Lifecycle event error`,e)}),this.registry=new P,this.cache=new d,this.graph=new m,this.observer=new M(this.registry,this.cache,this,this.logger),this.manager=new j(this.registry,this.cache,this.graph,this.store,this.observer,this.logger,this.events)}debugInfo(){let e=[];return this.registry.keys().forEach(t=>{let n=t,r=this.registry.getByString(n),i=this.cache.get(n);if(!r)return;let a=`idle`;i&&(i.scope===`singleton`&&i.debounceTimer!==void 0?a=`debouncing`:i.scope===`singleton`&&i.buildOnce.running()?a=`building`:i.error?a=`error`:i.instance!==void 0&&(a=`active`)),e.push({id:n,scope:r.scope??`singleton`,status:a,dependencies:this.graph.getDependencies(n).map(e=>String(e)),dependents:this.graph.getDependents(n).map(e=>String(e)),stateDependencies:i?.scope===`singleton`?Array.from(i.stateDependencies):[],buildCount:i?.buildCount??0})}),e}register(e){let{key:t}=e,n=t;this.registry.has(t)&&(this.logger.warn(`Overwriting artifact "${n}".`),this.manager.dispose(t).catch(e=>{this.logger.error(`Failed to dispose existing artifact "${n}"`,e)})),this.registry.register(e),this.graph.registerNode(t);let r=e.scope??`singleton`,i=e.lazy??!0;return this.events.emit({name:`artifact:registered`,payload:{key:n,scope:r}}),!i&&r===`singleton`&&this.resolve(t).catch(e=>{this.logger.error(`Eager load failed for "${n}"`,e)}),()=>this.unregister(t)}has(e){return this.registry.has(e)}async unregister(e,t){let n=t===void 0?e:this.manager.computeParamKey(e,t);await this.manager.dispose(n),await this.registry.unregister(n),this.observer.evictWatcher(n)}async resolve(e,t){return t===void 0?this.manager.resolveStatic(e):this.manager.resolveParameterized(e,t)}async require(e,t){let n=await this.resolve(e,t);if(n.error)throw n.error;return n.instance}watch(e,t,n){return t===void 0?this.observer.watch(e,n):this.observer.watchParameterized(e,t,n)}peek(e,t){let n=t===void 0?e:this.manager.computeParamKey(e,t);return this.cache.get(n)?.instance}async invalidate(e,t){let n=t?.params,r=t?.replace??!1,i=n===void 0?e:this.manager.computeParamKey(e,n);return this.manager.invalidate(i,r)}on(e,t){return this.events.subscribe(e,t)}once(e,t){return this.events.once(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){let e=this.registry.keys();await Promise.allSettled(e.map(e=>this.manager.dispose(e).catch(t=>{this.logger.error(`Failed to dispose artifact "${String(e)}"`,t)}))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear(),this.events.emit({name:`container:dispose`,payload:{}}),this.events.clear({permanent:!0})}async export(){let e=[];for(let t of this.cache.keys()){let n=this.cache.get(t);if(!n||n.scope!==`singleton`||n.instance===void 0)continue;let r=new Set;for(let e of n.stateGroups)for(let t of e.paths)r.add(t);let i=Array.from(r).sort(),a=this.store.subset(i),o=await u(JSON.stringify(a,Object.keys(a).sort())),s;try{s=structuredClone(n.instance)}catch{throw O(t)}e.push({key:t,instance:s,state:{groups:n.stateGroups.map(e=>({paths:e.paths,options:e.options})),hash:o},dependencies:Array.from(n.artifactDependencies)})}let t={version:`1.0`,timestamp:Date.now(),artifacts:e},n=await u(JSON.stringify(t));return{...t,checksum:n}}async restore(t){let{checksum:n,...r}=t;if(await u(JSON.stringify(r))!==n)throw D(`Bundle checksum mismatch – data corrupted`);if(t.version!==`1.0`)throw D(`Unsupported bundle version: ${t.version}`);let i=new Map;for(let e of t.artifacts)i.set(e.key,e);let a=new Set,o=new Map;for(let e of t.artifacts)for(let t of e.dependencies)o.has(t)||o.set(t,new Set),o.get(t).add(e.key);let s=async e=>{let t=new Set;for(let n of e.state.groups)for(let e of n.paths)t.add(e);let n=Array.from(t).sort(),r=this.store.subset(n);return u(JSON.stringify(r,Object.keys(r).sort()))};for(let e of t.artifacts)await s(e)!==e.state.hash&&a.add(e.key);let c=Array.from(a);for(;c.length;){let e=c.shift(),t=o.get(e);if(t)for(let e of t)a.has(e)||(a.add(e),c.push(e))}for(let n of t.artifacts){if(a.has(n.key))continue;this.cache.get(n.key)&&await this.cache.invalidateInstance(n.key,!1);let t={scope:`singleton`,instance:n.instance,error:void 0,version:1,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set(n.state.groups.flatMap(e=>e.paths)),activeDebounceMs:0,buildOnce:new e.Once({retry:!0,throws:!0}),streamSerializer:new e.Serializer({yieldMode:`microtask`}),invalidationSerializer:new e.Serializer({yieldMode:`macrotask`}),stateUnsubscribe:void 0,debounceTimer:void 0,controller:new AbortController,streamOnce:new e.Once({retry:!0,throws:!0}),stream:void 0,stateGroups:n.state.groups,artifactDependencies:new Set(n.dependencies)};t.buildOnce.resolve(n.instance),this.cache.set(n.key,t);let r=[];for(let e of n.state.groups){let t=this.store.watch(e.paths,()=>this.invalidate(n.key),e.options);r.push(t)}t.stateUnsubscribe=()=>{for(let e of r)e()},this.graph.setDependencies(n.key,n.dependencies)}}static async from(e){let n=new t(e.store,{logger:e.logger});if(e.bundle){if(typeof e.bundle!=`object`||!e.bundle.version||!Array.isArray(e.bundle.artifacts))throw D(`Invalid bundle: missing version or artifacts array`);await n.restore(e.bundle)}for(let t of e.templates)n.register(t);return n}};exports.ArtifactContainer=F,exports.ArtifactScopes=N,exports.ErrorCodes=h,exports.SupersededBuildError=k,Object.defineProperty(exports,"SystemError",{enumerable:!0,get:function(){return n.SystemError}}),exports.artifactNotFound=_,exports.buildStaleAfterRetries=E,exports.cycleDetected=v,exports.illegalScope=y,exports.invalidExport=O,exports.invalidImport=D,exports.keyConflict=S,exports.notParameterized=C,exports.paramKeyCollision=w,exports.selfDependency=T,exports.timeoutError=x,exports.watcherDisposed=b;
package/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{CommonErrors as e,SystemError as t,SystemError as n}from"@asaidimu/utils-error";import{createEventBus as r}from"@asaidimu/utils-events";import{ConsoleSink as i,Logger as a}from"@asaidimu/utils-logger";var o=class e extends n{constructor(t,n){super({code:`SYNC_ERROR`,message:t,cause:n}),this.name=`SyncError`,Object.setPrototypeOf(this,e.prototype)}},s=class e extends o{constructor(t){super(`[ArtifactContainer] Operation timed out: ${t}`),this.name=`TimeoutError`,Object.setPrototypeOf(this,e.prototype)}},c=class e extends o{constructor(t){super(`[Serializer] The serializer has been marked as done!`,t),this.name=`SerializerExecutionDone`,Object.setPrototypeOf(this,e.prototype)}},l=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){this._locked=!0;return}if(this.waiters.length>=this._capacity)throw Error(`Mutex queue is full (capacity: ${this._capacity})`);let t,n=new Promise(e=>t=e);if(this.waiters.push(t),e==null){await n;return}let r;await Promise.race([n.then(()=>clearTimeout(r)),new Promise((n,i)=>{r=setTimeout(()=>{let e=this.waiters.indexOf(t);e!==-1&&this.waiters.splice(e,1),i(new s(`Mutex lock timed out`))},e)})])}tryLock(){return this._locked?!1:(this._locked=!0,!0)}unlock(){if(!this._locked)throw Error(`Mutex is not locked`);let e=this.waiters.shift();e?this._yieldMode===`microtask`?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},u=class{mutex=new l({yieldMode:`microtask`});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=!!e,this.throws=!!t}resolve(e){if(this._done)throw Error(`Cannot resolve: operation is already completed.`);if(this.running())throw Error(`Cannot resolve: operation is currently running.`);this._value=e,this._done=!0}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){let e=Error(`Cannot execute doSync while an async operation is pending.`);if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){let e=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()}let e=Error(`Cannot execute doSync while an async operation is pending.`);if(this.throws)throw e;return{value:null,error:e}}try{let 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 this.promise!==null&&!this.done()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw Error(`Once operation is not yet complete`);if(this._error)throw this._error;return this._value}reset(){if(this.running())throw 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,n=`Operation timed out`){if(t==null)return e;let r;return Promise.race([e.then(e=>(clearTimeout(r),e)),new Promise((e,i)=>{r=setTimeout(()=>i(new s(n)),t)})])}},d=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new l({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 n=null,r;try{if(this._done)throw new c;n=await e(),this._lastValue=n,this._lastError=void 0,this._hasRun=!0}catch(e){r=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:n,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()}},f=class{factory;onCleanup;options;_count=0;init=new u({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;constructor(e,t,n={}){this.factory=e,this.onCleanup=t,this.options=n}get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;let e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){if(this._count<=0){console.warn(`SharedResource.release() called, but count is already 0.`);return}this._count--,this._count===0&&this.scheduleCleanup()}peek(){let e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,this.cleanupTimer!==void 0&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){let e=this.options.gracePeriod??`microtask`;if(e===`sync`){this.executeCleanup();return}if(e===`microtask`){this.pendingMicrotask=!0,queueMicrotask(()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())});return}this.cleanupTimer=setTimeout(()=>{this.cleanupTimer=void 0,!(this._count>0)&&this.executeCleanup()},e)}executeCleanup(){let 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;let n=e.slice(),r=t?`[${t}]`:`[ArtifactCleanup]`;return async()=>{for(let e=n.length-1;e>=0;e--)try{await n[e]()}catch(t){console.error(`${r} Cleanup error at index ${e}:`,t)}}}async function m(e,t){let n=t?`[${t}]`:`[ArtifactCleanup]`;for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${n} Cleanup error at index ${t}:`,e)}}function h(e){return`${e}__watched`}const g=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function _(e,t){let n,r=new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Timeout: ${t}ms`)),t)});try{return Promise.race([e,r])}finally{clearTimeout(n)}}async function v(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}var y=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,n){let r=this.get(e);if(!r)return g;if(r.package)return r.package;let i=e,a=p(r.cleanupFunctions,i),o=r.scope===`singleton`?r.instance!==void 0:!0,s={instance:r.instance,error:r.error,ready:o,[n||e]:r.instance,cleanup:a,invalidate:t};return r.package=s,s}invalidatePackage(e){let t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(e,t=!1){let n=this.get(e);if(!n)return;let r=e;n.scope===`singleton`&&(n.stateUnsubscribe&&=(n.stateUnsubscribe(),void 0),n.debounceTimer&&=(clearTimeout(n.debounceTimer),void 0),n.controller.abort(),await n.streamOnce.current(),n.streamSerializer.close(),n.stream=void 0,n.streamOnce=new u({retry:!0,throws:!0}),t||(n.streamSerializer=new d,n.controller=new AbortController)),await m(n.cleanupFunctions,r),await m(n.disposeFunctions,r),n.cleanupFunctions=[],n.disposeFunctions=[],n.scope===`singleton`&&(n.buildOnce=new u({retry:!0,throws:!0})),n.instance=void 0,n.error=void 0}},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;let t=this.dependencies.get(e);if(t)for(let n of t)this.dependents.get(n)?.delete(e);let n=this.dependents.get(e);if(n)for(let t of n)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){let t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){let t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??x}setDependencies(e,t){this.registerNode(e);let n=this.dependencies.get(e),r=new Set(t);for(let t of n)r.has(t)||this.removeDependency(e,t);for(let t of r)n.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];let n=[t],r=new Set([t]),i=new Map;for(;n.length>0;){let a=n.shift();if(a===e){let n=[],r=e;for(;r!==void 0&&(n.push(r),r!==t);)r=i.get(r);return n.reverse(),n.unshift(e),n}let o=this.dependencies.get(a);if(o)for(let e of o)r.has(e)||(r.add(e),i.set(e,a),n.push(e))}return null}topologicalSort(){let e=new Map,t=Array.from(this.dependencies.keys());for(let n of t)e.set(n,this.dependencies.get(n)?.size??0);let n=[];for(let[t,r]of e)r===0&&n.push(t);let r=[];for(;n.length>0;){let t=n.shift();r.push(t);let i=this.dependents.get(t);if(i)for(let t of i){let r=(e.get(t)||0)-1;e.set(t,r),r===0&&n.push(t)}}if(r.length!==t.length)throw Error(`Cycle detected in graph; topological sort impossible.`);return r}getTransitiveDependencies(e,t=!1){return this.bfs(e,`dependencies`,t)}getTransitiveDependents(e,t=!1){return this.bfs(e,`dependents`,t)}bfs(e,t,n){let r=new Set,i=new Set,a=[e];i.add(e),n&&r.add(e);let o=t===`dependencies`?this.dependencies:this.dependents;for(;a.length>0;){let e=a.shift(),t=o.get(e);if(t)for(let e of t)i.has(e)||(i.add(e),r.add(e),a.push(e))}return r}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])=>{let n=Array.from(t).join(`, `);return`${String(e)} → [${n||`∅`}]`}).join(`
2
- `)}};const x=new Set;var 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){let n=Array.from(t).map(e=>e);this.graph.setDependencies(e,n)}wouldCreateCycle(e,t,n){if(n?.has(t)){let e=Array.from(n),r=e.indexOf(t),i=e.slice(r);return i.push(t),i}return this.graph.wouldCreateCycle(e,t)||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()}};const C=[`map`,`filter`,`reduce`,`forEach`,`find`,`findIndex`,`some`,`every`,`includes`,`flatMap`,`flat`,`slice`,`splice`];function w(e,t=`.`){let n=new Set,r=new Map,i=(e=``)=>{if(r.has(e))return r.get(e);let a=new Proxy(()=>{},{get:(r,a)=>{if(typeof a==`symbol`||a===`then`)return;if(a===`valueOf`||a===`toString`)throw Error(`Cannot perform logic, arithmetic, or string operations inside a selector.`);if(C.includes(a))throw Error(`Array method .${a}() is not allowed in selectors.`);let o=e?`${e}${t}${a}`:a;return e&&n.delete(e),n.add(o),i(o)},has:()=>{throw Error(`The 'in' operator is not allowed in selectors.`)},apply:()=>{throw Error(`Selectors cannot call functions or methods.`)}});return r.set(e,a),a};try{e(i())}catch(e){throw Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(n)}const T={NOT_FOUND:e.NOT_FOUND,DUPLICATE_KEY:e.DUPLICATE_KEY,INVALID_COMMAND:e.INVALID_COMMAND,INTERNAL_ERROR:e.INTERNAL_ERROR,CONCURRENCY_ERROR:e.CONCURRENCY_ERROR},E=`[ArtifactContainer]`;function D(e){return new n({code:T.NOT_FOUND,message:`${E} Artifact "${e}" not found.`,operation:`artifact:resolve`})}function O(e){return new n({code:T.INTERNAL_ERROR,message:`${E} Cycle detected: ${e.join(` -> `)}`,operation:`artifact:resolve`})}function k(e){return new n({code:T.INVALID_COMMAND,message:`${E} ${e}`,operation:`artifact:build`})}function A(e){return new n({code:T.INTERNAL_ERROR,message:`${E} Artifact with key:${e} has already been disposed`,operation:`artifact:watch`})}function j(e){return new n({code:T.CONCURRENCY_ERROR,message:`${E} Operation timed out: ${e}`,operation:`artifact:build`})}function M(e){return new n({code:T.DUPLICATE_KEY,message:`${E} An artifact with key:"${e}" already exists!`,operation:`artifact:register`})}function N(e){return new n({code:T.INVALID_COMMAND,message:`${E} Artifact "${e}" is not parameterized.`,operation:`artifact:resolve`})}function P(e,t){return new n({code:T.DUPLICATE_KEY,message:`${E} Parameterized artifact "${e}" with params resolves to key "${t}" which is already registered as a static artifact.`,operation:`artifact:resolve`})}function F(e){return new n({code:T.INTERNAL_ERROR,message:`${E} Artifact "${e}" depends on itself.`,operation:`artifact:build`})}function I(e){return new n({code:T.CONCURRENCY_ERROR,message:`${E} Build stale after all retries: dependency "${String(e)}" changed during build.`,operation:`artifact:build`})}function L(e){return new n({code:T.INVALID_COMMAND,message:e,operation:`artifact:import`})}function R(e){return new n({code:T.INTERNAL_ERROR,message:`${E} Artifact "${e}" instance is not JSON-serializable (POJO are required for persistence)`,operation:`artifact:export`})}var z=class extends Error{constructor(){super(`Build superseded by invalidation`),this.name=`SupersededBuildError`}};const B=new AbortController().signal;var V=class{registry;cache;graph;store;observer;logger;events;constructor(e,t,n,r,i,a,o){this.registry=e,this.cache=t,this.graph=n,this.store=r,this.observer=i,this.logger=a,this.events=o}async build(e,t,n){let r=this.cache.get(e);if(r?.scope===`singleton`&&r.buildOnce.done())return this.cache.package(e,(t,n)=>this.invalidate(e,t,n),n);let i=this.registry.getByString(e);if(!i)throw D(e);let a=t??[];if(a.includes(e))throw O([...a,e].map(String));a.push(e);let o=r;o||(o=this.createCachedArtifact(i),this.cache.set(e,o)),this.events?.emit({name:`build:start`,payload:{key:e,templateKey:n}});try{if(o.scope===`transient`)return this.executeBuild(i,o,a);let r=o;try{await r.buildOnce.do(()=>this.executeBuild(i,r,a))}catch(r){if(r instanceof z)return this.build(e,t,n);throw r}return r.stream&&r.streamOnce.do(r.stream),this.events?.emit({name:`build:complete`,payload:{key:e,instance:o.instance}}),this.cache.package(e,(t,n)=>this.invalidate(e,t,n),n)}catch(t){throw t instanceof z||this.events?.emit({name:`build:error`,payload:{key:e,error:t}}),t}finally{a.pop()}}async executeBuild(e,t,n){let r=e.key,i=String(r),a=t.scope===`transient`;t.buildCount++,t.scope===`singleton`&&(t.activeDebounceMs=e.debounce??0);let o={cleanupFunctions:[],disposeFunctions:[],capturedArtifactDeps:new Set,capturedStateSelectors:[],dependencyVersions:new Map},s=this.buildContext(e,t,n,i,o),c=await this.runWithRetries(e,s,o.dependencyVersions);if(this.commitResult(r,t,a,c,o),a){let e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[r]:e,cleanup:p(o.cleanupFunctions,i),invalidate:async()=>this.logger.warn(`Cannot invalidate transient "${i}"`)}}}buildContext(e,t,n,r,i){let a=e.key,o=t.scope===`transient`,{cleanupFunctions:s,disposeFunctions:c,capturedArtifactDeps:l,dependencyVersions:u,capturedStateSelectors:d}=i,f=async(e,t)=>{let i=t?this.computeParamKey(e,t):e;if(i===a)throw F(r);let o=this.graph.wouldCreateCycle(a,i);if(o)throw O(o);l.add(i);let s=await(t?this.resolveParameterized(e,t):this.build(e,n)),c=this.cache.get(i);return c&&u.set(i,c.version),s},p=t.scope===`singleton`?t.controller.signal:B,m=async(e,t)=>{let n=await f(e,t);if(n.error)throw n.error;return n.instance},h=(e,t)=>{let n=w(e);return d.push({paths:n,options:t}),e(this.store.get(!0))};return{state:()=>this.store.get(!0),previous:t.instance,signal:p,onCleanup:e=>s.push(e),onDispose:e=>c.push(e),use:e=>e({resolve:f,require:m,select:h}),stream:e=>{if(o)throw k(`Illegal stream on transient artifact "${r}"`);let n=t,i=async(e,t=void 0)=>{await n.streamSerializer.do(async()=>{n.stream!==void 0&&(n.instance=e,n.error=t,n.version++,this.cache.invalidatePackage(a),await this.processStream(r),this.events?.emit({name:`stream:emit`,payload:{key:r,value:e}}))})},s={value:()=>n.instance,get signal(){return n.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>i(e)};n.stream=async()=>{try{let t=await e(s);t&&n.cleanupFunctions.push(t)}catch(e){await i(void 0,e),await this.invalidate(a,!1,!0)}}}}}async runWithRetries(e,n,r){let i=n.signal,a=(e.retries??0)+1,o=0;for(;o<a;)try{if(i.aborted)throw new z;let t=e.factory(n),s;if(s=t instanceof Promise?e.timeout?await _(t,e.timeout):await t:t,i.aborted)throw new z;let c=this.detectStaleness(r);if(c){if(o++,r.clear(),o<a)continue;return{ok:!1,error:I(String(c))}}return{ok:!0,value:s}}catch(e){if(i.aborted||e instanceof z)throw new z;if(e instanceof t)throw e;if(o++,o>=a)return{ok:!1,error:e}}return{ok:!1,error:Error(`Build exhausted retry budget unexpectedly.`)}}commitResult(e,t,n,r,i){let{cleanupFunctions:a,disposeFunctions:o,capturedArtifactDeps:s,capturedStateSelectors:c}=i;n||(this.updateDependencyGraph(e,s,c),t.cleanupFunctions=a,t.disposeFunctions=o,t.artifactDependencies=new Set(s),t.stateGroups=c.map(({paths:e,options:t})=>({paths:e,options:t}))),r.ok?(t.instance=r.value,t.error=void 0):(t.instance=void 0,t.error=r.error),t.version++,this.cache.invalidatePackage(e)}detectStaleness(e){for(let[t,n]of e){let e=this.cache.get(t);if(e&&e.version!==n)return t}return null}async invalidate(e,t=!1,n=!1){let r=this.cache.get(e);if(!r)return;if(r.scope!==`singleton`)return this.executeInvalidation(e,t,n);let i=r;return i.debounceTimer&&=(clearTimeout(i.debounceTimer),void 0),!t&&i.activeDebounceMs>0?new Promise((r,a)=>{i.debounceTimer=setTimeout(()=>{i.debounceTimer=void 0,this.executeInvalidation(e,t,n).then(r).catch(a)},i.activeDebounceMs)}):this.executeInvalidation(e,t,n)}async executeInvalidation(e,t,n=!1){let r=this.cache.get(e);!r||r.scope!==`singleton`||await r.invalidationSerializer.do(async()=>{r.version++,await this.cache.invalidateInstance(e);let i=this.graph.iterDependents(e),a=i.size>0;await this.cascadeInvalidation(i),this.events?.emit({name:`artifact:invalidated`,payload:{key:e,cascade:a,replace:t}});let o=this.registry.get(e),s=o&&(t||!o.lazy||this.observer.hasWatchers(e))&&!n;s&&await this.build(e).catch(t=>{t instanceof z||this.logger.error(`Rebuild failed for "${String(e)}"`,t)}),(s||n)&&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),this.events?.emit({name:`artifact:disposed`,payload:{key:e}}))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(e.size===0)return;let t=[];for(let n of e)t.push(this.invalidate(n).catch(e=>{this.logger.error(`Cascade failed for "${String(n)}"`,e)}));await Promise.all(t)}updateDependencyGraph(e,t,n){let r=this.cache.get(e);if(!r||r.scope!==`singleton`)return;this.graph.registerNode(e),this.graph.setDependencies(e,t),r.stateDependencies=new Set;for(let{paths:e}of n)for(let t of e)r.stateDependencies.add(t);if(r.stateUnsubscribe&&=(r.stateUnsubscribe(),void 0),n.length===0)return;let i=()=>this.invalidate(e),a=new Map;for(let{paths:e,options:t}of n){let n=t===void 0?`undefined`:JSON.stringify(t),r=a.get(n);r||(r={options:t,paths:new Set},a.set(n,r));for(let t of e)r.paths.add(t)}let o=[];for(let{options:e,paths:t}of a.values()){if(t.size===0)continue;let n=Array.from(t);e===void 0?o.push(this.store.watch(n,i)):o.push(this.store.watch(n,i,e))}o.length===0?r.stateUnsubscribe=void 0:o.length===1?r.stateUnsubscribe=o[0]:r.stateUnsubscribe=()=>{for(let e of o)e()}}createCachedArtifact(e){return e.scope===`transient`?{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 u({retry:!0,throws:!0}),streamOnce:new u({retry:!0,throws:!0}),streamSerializer:new d({yieldMode:`microtask`}),invalidationSerializer:new d({yieldMode:`macrotask`}),stateGroups:[],artifactDependencies:new Set}}resolveStatic(e){if(!this.registry.getByString(e))throw D(e);return this.build(e)}async resolveParameterized(e,t){let n=this.registry.getByString(e);if(!n)throw D(String(e));if(!n.paramKey)throw N(String(e));let r=n.paramKey(t),i=this.registry.getByString(r);if(i&&!i.paramKey&&!i.virtual)throw P(String(e),r);return this.registry.hasString(r)||this.registry.setVirtual(r,{key:r,factory:e=>n.factory({...e,params:t}),scope:n.scope,lazy:n.lazy,timeout:n.timeout,retries:n.retries,debounce:n.debounce,virtual:!0}),this.build(r,void 0,e)}computeParamKey(e,t){let n=this.registry.getByString(e);if(!n||!n.paramKey)throw N(String(e));return n.paramKey(t)}},H=class{registry;cache;container;logger;listeners=new Map;watchers=new Map;constructor(e,t,n,r){this.registry=e,this.cache=t,this.container=n,this.logger=r}watch(e,t=60*1e3){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,n=60*1e3){let r=this.registry.get(e);if(!r.paramKey)throw Error(`Artifact "${String(e)}" is not parameterized.`);let i=r.paramKey(t);return this.watchForKey(i,r,n,t)}watchForKey(e,t,n,r){let i=t.scope===`transient`,a=i?h(e):e,o=this.watchers.get(a);if(o)return o.observer;let s=new f(async()=>{(i||r!==void 0)&&!this.registry.hasString(e)&&this.registry.setVirtual(e,{key:e,factory:i?t.factory:e=>t.factory({...e,params:r}),scope:i?`singleton`:t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})},async()=>{i||r!==void 0?(await this.registry.unregister(a).catch(()=>{}),this.cache.delete(a),this.watchers.delete(a)):this.cache.invalidatePackage(a),this.listeners.delete(a)},{gracePeriod:i&&r===void 0?`sync`:n}),c,l={id:a,get count(){return s.subscribers},get:(t=!1)=>s.subscribers===0&&!t?g:this.cache.package(a,(e,t)=>this.container.invalidate(a,e,t),e),resolve:()=>c||(c=(async()=>{await s.acquire();try{return await this.container.resolve(a)}finally{s.release(),c=void 0}})(),c),subscribe:(e,t=!0)=>{let n=()=>e(l.get());return s.acquire().then(()=>{this.container.resolve(a).then(()=>{this.listeners.has(a)||this.listeners.set(a,new Set),t&&n(),this.listeners.get(a).add(n)})}).catch(e=>{this.logger.error(`Resolution failed for "${a}"`,e),this.listeners.get(a)?.add(n)}),()=>{this.listeners.get(a)?.delete(n),s.release()}}};return this.watchers.set(a,{resource:s,observer:l}),l}evictWatcher(e){[e,h(e)].forEach(e=>{let t=this.watchers.get(e);t&&(t.resource.forceCleanup(),this.watchers.delete(e))})}notify(e){let t=this.listeners.get(e);if(!(!t||t.size===0))for(let n of t)try{n()}catch(t){this.logger.error(`Listener error for "${e}"`,t)}}hasWatchers(e){return this.watchers.has(e)||this.watchers.has(h(e))}getWatcherCount(e){return(this.watchers.get(e)||this.watchers.get(h(e)))?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}};let U=function(e){return e.Singleton=`singleton`,e.Transient=`transient`,e}({});var W=class{artifacts=new Map;register({key:e,factory:t,lazy:n,...r}){let{scope:i,...a}=r,o={key:e,factory:t,scope:r.scope??`singleton`,lazy:n===void 0?!0:n,...a};return this.artifacts.set(e,o),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw D(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()}},G=class e{registry;cache;graph;manager;observer;logger;store;events;constructor(e,t){this.logger=t?.logger??new a([new i],{module:`artifacts`}),this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t),subset:(...t)=>e.subset(...t)},this.events=r({errorHandler:e=>this.logger.error(`Lifecycle event error`,e)}),this.registry=new W,this.cache=new y,this.graph=new S,this.observer=new H(this.registry,this.cache,this,this.logger),this.manager=new V(this.registry,this.cache,this.graph,this.store,this.observer,this.logger,this.events)}debugInfo(){let e=[];return this.registry.keys().forEach(t=>{let n=t,r=this.registry.getByString(n),i=this.cache.get(n);if(!r)return;let a=`idle`;i&&(i.scope===`singleton`&&i.debounceTimer!==void 0?a=`debouncing`:i.scope===`singleton`&&i.buildOnce.running()?a=`building`:i.error?a=`error`:i.instance!==void 0&&(a=`active`)),e.push({id:n,scope:r.scope??`singleton`,status:a,dependencies:this.graph.getDependencies(n).map(e=>String(e)),dependents:this.graph.getDependents(n).map(e=>String(e)),stateDependencies:i?.scope===`singleton`?Array.from(i.stateDependencies):[],buildCount:i?.buildCount??0})}),e}register(e){let{key:t}=e,n=t;this.registry.has(t)&&(this.logger.warn(`Overwriting artifact "${n}".`),this.manager.dispose(t).catch(e=>{this.logger.error(`Failed to dispose existing artifact "${n}"`,e)})),this.registry.register(e),this.graph.registerNode(t);let r=e.scope??`singleton`,i=e.lazy??!0;return this.events.emit({name:`artifact:registered`,payload:{key:n,scope:r}}),!i&&r===`singleton`&&this.resolve(t).catch(e=>{this.logger.error(`Eager load failed for "${n}"`,e)}),()=>this.unregister(t)}has(e){return this.registry.has(e)}async unregister(e,t){let n=t===void 0?e:this.manager.computeParamKey(e,t);await this.manager.dispose(n),await this.registry.unregister(n),this.observer.evictWatcher(n)}async resolve(e,t){return t===void 0?this.manager.resolveStatic(e):this.manager.resolveParameterized(e,t)}async require(e,t){let n=await this.resolve(e,t);if(n.error)throw n.error;return n.instance}watch(e,t,n){return t===void 0?this.observer.watch(e,n):this.observer.watchParameterized(e,t,n)}peek(e,t){let n=t===void 0?e:this.manager.computeParamKey(e,t);return this.cache.get(n)?.instance}async invalidate(e,t){let n=t?.params,r=t?.replace??!1,i=n===void 0?e:this.manager.computeParamKey(e,n);return this.manager.invalidate(i,r)}on(e,t){return this.events.subscribe(e,t)}once(e,t){return this.events.once(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){let e=this.registry.keys();await Promise.allSettled(e.map(e=>this.manager.dispose(e).catch(t=>{this.logger.error(`Failed to dispose artifact "${String(e)}"`,t)}))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear(),this.events.emit({name:`container:dispose`,payload:{}}),this.events.clear({permanent:!0})}async export(){let e=[];for(let t of this.cache.keys()){let n=this.cache.get(t);if(!n||n.scope!==`singleton`||n.instance===void 0)continue;let r=new Set;for(let e of n.stateGroups)for(let t of e.paths)r.add(t);let i=Array.from(r).sort(),a=this.store.subset(i),o=await v(JSON.stringify(a,Object.keys(a).sort())),s;try{s=structuredClone(n.instance)}catch{throw R(t)}e.push({key:t,instance:s,state:{groups:n.stateGroups.map(e=>({paths:e.paths,options:e.options})),hash:o},dependencies:Array.from(n.artifactDependencies)})}let t={version:`1.0`,timestamp:Date.now(),artifacts:e},n=await v(JSON.stringify(t));return{...t,checksum:n}}async restore(e){let{checksum:t,...n}=e;if(await v(JSON.stringify(n))!==t)throw L(`Bundle checksum mismatch – data corrupted`);if(e.version!==`1.0`)throw L(`Unsupported bundle version: ${e.version}`);let r=new Map;for(let t of e.artifacts)r.set(t.key,t);let i=new Set,a=new Map;for(let t of e.artifacts)for(let e of t.dependencies)a.has(e)||a.set(e,new Set),a.get(e).add(t.key);let o=async e=>{let t=new Set;for(let n of e.state.groups)for(let e of n.paths)t.add(e);let n=Array.from(t).sort(),r=this.store.subset(n);return v(JSON.stringify(r,Object.keys(r).sort()))};for(let t of e.artifacts)await o(t)!==t.state.hash&&i.add(t.key);let s=Array.from(i);for(;s.length;){let e=s.shift(),t=a.get(e);if(t)for(let e of t)i.has(e)||(i.add(e),s.push(e))}for(let t of e.artifacts){if(i.has(t.key))continue;this.cache.get(t.key)&&await this.cache.invalidateInstance(t.key,!1);let e={scope:`singleton`,instance:t.instance,error:void 0,version:1,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set(t.state.groups.flatMap(e=>e.paths)),activeDebounceMs:0,buildOnce:new u({retry:!0,throws:!0}),streamSerializer:new d({yieldMode:`microtask`}),invalidationSerializer:new d({yieldMode:`macrotask`}),stateUnsubscribe:void 0,debounceTimer:void 0,controller:new AbortController,streamOnce:new u({retry:!0,throws:!0}),stream:void 0,stateGroups:t.state.groups,artifactDependencies:new Set(t.dependencies)};e.buildOnce.resolve(t.instance),this.cache.set(t.key,e);let n=[];for(let e of t.state.groups){let r=this.store.watch(e.paths,()=>this.invalidate(t.key),e.options);n.push(r)}e.stateUnsubscribe=()=>{for(let e of n)e()},this.graph.setDependencies(t.key,t.dependencies)}}static async from(t){let n=new e(t.store,{logger:t.logger});if(t.bundle){if(typeof t.bundle!=`object`||!t.bundle.version||!Array.isArray(t.bundle.artifacts))throw L(`Invalid bundle: missing version or artifacts array`);await n.restore(t.bundle)}for(let e of t.templates)n.register(e);return n}};export{G as ArtifactContainer,U as ArtifactScopes,T as ErrorCodes,z as SupersededBuildError,t as SystemError,D as artifactNotFound,I as buildStaleAfterRetries,O as cycleDetected,k as illegalScope,R as invalidExport,L as invalidImport,M as keyConflict,N as notParameterized,P as paramKeyCollision,F as selfDependency,j as timeoutError,A as watcherDisposed};
1
+ import{Once as e,Serializer as t,SharedResource as n}from"@asaidimu/utils-sync";import{buildPaths as r}from"@asaidimu/utils-store";import{CommonErrors as i,SystemError as a,SystemError as o}from"@asaidimu/utils-error";import{createEventBus as s}from"@asaidimu/utils-events";import{ConsoleSink as c,Logger as l}from"@asaidimu/utils-logger";function u(e,t){if(!e.length)return;let n=e.slice(),r=t?`[${t}]`:`[ArtifactCleanup]`;return async()=>{for(let e=n.length-1;e>=0;e--)try{await n[e]()}catch(t){console.error(`${r} Cleanup error at index ${e}:`,t)}}}async function d(e,t){let n=t?`[${t}]`:`[ArtifactCleanup]`;for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${n} Cleanup error at index ${t}:`,e)}}function f(e){return`${e}__watched`}const p=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function m(e,t){let n,r=new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Timeout: ${t}ms`)),t)});try{return Promise.race([e,r])}finally{clearTimeout(n)}}async function h(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}var g=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,n){let r=this.get(e);if(!r)return p;if(r.package)return r.package;let i=e,a=u(r.cleanupFunctions,i),o=r.scope===`singleton`?r.instance!==void 0:!0,s={instance:r.instance,error:r.error,ready:o,[n||e]:r.instance,cleanup:a,invalidate:t};return r.package=s,s}invalidatePackage(e){let t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(n,r=!1){let i=this.get(n);if(!i)return;let a=n;i.scope===`singleton`&&(i.stateUnsubscribe&&=(i.stateUnsubscribe(),void 0),i.debounceTimer&&=(clearTimeout(i.debounceTimer),void 0),i.controller.abort(),await i.streamOnce.current(),i.streamSerializer.close(),i.stream=void 0,i.streamOnce=new e({retry:!0,throws:!0}),r||(i.streamSerializer=new t,i.controller=new AbortController)),await d(i.cleanupFunctions,a),await d(i.disposeFunctions,a),i.cleanupFunctions=[],i.disposeFunctions=[],i.scope===`singleton`&&(i.buildOnce=new e({retry:!0,throws:!0})),i.instance=void 0,i.error=void 0}},_=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;let t=this.dependencies.get(e);if(t)for(let n of t)this.dependents.get(n)?.delete(e);let n=this.dependents.get(e);if(n)for(let t of n)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){let t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){let t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??v}setDependencies(e,t){this.registerNode(e);let n=this.dependencies.get(e),r=new Set(t);for(let t of n)r.has(t)||this.removeDependency(e,t);for(let t of r)n.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];let n=[t],r=new Set([t]),i=new Map;for(;n.length>0;){let a=n.shift();if(a===e){let n=[],r=e;for(;r!==void 0&&(n.push(r),r!==t);)r=i.get(r);return n.reverse(),n.unshift(e),n}let o=this.dependencies.get(a);if(o)for(let e of o)r.has(e)||(r.add(e),i.set(e,a),n.push(e))}return null}topologicalSort(){let e=new Map,t=Array.from(this.dependencies.keys());for(let n of t)e.set(n,this.dependencies.get(n)?.size??0);let n=[];for(let[t,r]of e)r===0&&n.push(t);let r=[];for(;n.length>0;){let t=n.shift();r.push(t);let i=this.dependents.get(t);if(i)for(let t of i){let r=(e.get(t)||0)-1;e.set(t,r),r===0&&n.push(t)}}if(r.length!==t.length)throw Error(`Cycle detected in graph; topological sort impossible.`);return r}getTransitiveDependencies(e,t=!1){return this.bfs(e,`dependencies`,t)}getTransitiveDependents(e,t=!1){return this.bfs(e,`dependents`,t)}bfs(e,t,n){let r=new Set,i=new Set,a=[e];i.add(e),n&&r.add(e);let o=t===`dependencies`?this.dependencies:this.dependents;for(;a.length>0;){let e=a.shift(),t=o.get(e);if(t)for(let e of t)i.has(e)||(i.add(e),r.add(e),a.push(e))}return r}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])=>{let n=Array.from(t).join(`, `);return`${String(e)} → [${n||`∅`}]`}).join(`
2
+ `)}};const v=new Set;var y=class{graph;constructor(){this.graph=new _}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){let n=Array.from(t).map(e=>e);this.graph.setDependencies(e,n)}wouldCreateCycle(e,t,n){if(n?.has(t)){let e=Array.from(n),r=e.indexOf(t),i=e.slice(r);return i.push(t),i}return this.graph.wouldCreateCycle(e,t)||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()}};const b={NOT_FOUND:i.NOT_FOUND,DUPLICATE_KEY:i.DUPLICATE_KEY,INVALID_COMMAND:i.INVALID_COMMAND,INTERNAL_ERROR:i.INTERNAL_ERROR,CONCURRENCY_ERROR:i.CONCURRENCY_ERROR},x=`[ArtifactContainer]`;function S(e){return new o({code:b.NOT_FOUND,message:`${x} Artifact "${e}" not found.`,operation:`artifact:resolve`})}function C(e){return new o({code:b.INTERNAL_ERROR,message:`${x} Cycle detected: ${e.join(` -> `)}`,operation:`artifact:resolve`})}function w(e){return new o({code:b.INVALID_COMMAND,message:`${x} ${e}`,operation:`artifact:build`})}function T(e){return new o({code:b.INTERNAL_ERROR,message:`${x} Artifact with key:${e} has already been disposed`,operation:`artifact:watch`})}function E(e){return new o({code:b.CONCURRENCY_ERROR,message:`${x} Operation timed out: ${e}`,operation:`artifact:build`})}function D(e){return new o({code:b.DUPLICATE_KEY,message:`${x} An artifact with key:"${e}" already exists!`,operation:`artifact:register`})}function O(e){return new o({code:b.INVALID_COMMAND,message:`${x} Artifact "${e}" is not parameterized.`,operation:`artifact:resolve`})}function k(e,t){return new o({code:b.DUPLICATE_KEY,message:`${x} Parameterized artifact "${e}" with params resolves to key "${t}" which is already registered as a static artifact.`,operation:`artifact:resolve`})}function A(e){return new o({code:b.INTERNAL_ERROR,message:`${x} Artifact "${e}" depends on itself.`,operation:`artifact:build`})}function j(e){return new o({code:b.CONCURRENCY_ERROR,message:`${x} Build stale after all retries: dependency "${String(e)}" changed during build.`,operation:`artifact:build`})}function M(e){return new o({code:b.INVALID_COMMAND,message:e,operation:`artifact:import`})}function N(e){return new o({code:b.INTERNAL_ERROR,message:`${x} Artifact "${e}" instance is not JSON-serializable (POJO are required for persistence)`,operation:`artifact:export`})}var P=class extends Error{constructor(){super(`Build superseded by invalidation`),this.name=`SupersededBuildError`}};const F=new AbortController().signal;var I=class{registry;cache;graph;store;observer;logger;events;constructor(e,t,n,r,i,a,o){this.registry=e,this.cache=t,this.graph=n,this.store=r,this.observer=i,this.logger=a,this.events=o}async build(e,t,n){let r=this.cache.get(e);if(r?.scope===`singleton`&&r.buildOnce.done())return this.cache.package(e,(t,n)=>this.invalidate(e,t,n),n);let i=this.registry.getByString(e);if(!i)throw S(e);let a=t??[];if(a.includes(e))throw C([...a,e].map(String));a.push(e);let o=r;o||(o=this.createCachedArtifact(i),this.cache.set(e,o)),this.events?.emit({name:`build:start`,payload:{key:e,templateKey:n}});try{if(o.scope===`transient`)return this.executeBuild(i,o,a);let r=o;try{await r.buildOnce.do(()=>this.executeBuild(i,r,a))}catch(r){if(r instanceof P)return this.build(e,t,n);throw r}return r.stream&&r.streamOnce.do(r.stream),this.events?.emit({name:`build:complete`,payload:{key:e,instance:o.instance}}),this.cache.package(e,(t,n)=>this.invalidate(e,t,n),n)}catch(t){throw t instanceof P||this.events?.emit({name:`build:error`,payload:{key:e,error:t}}),t}finally{a.pop()}}async executeBuild(e,t,n){let r=e.key,i=String(r),a=t.scope===`transient`;t.buildCount++,t.scope===`singleton`&&(t.activeDebounceMs=e.debounce??0);let o={cleanupFunctions:[],disposeFunctions:[],capturedArtifactDeps:new Set,capturedStateSelectors:[],dependencyVersions:new Map},s=this.buildContext(e,t,n,i,o),c=await this.runWithRetries(e,s,o.dependencyVersions);if(this.commitResult(r,t,a,c,o),a){let e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[r]:e,cleanup:u(o.cleanupFunctions,i),invalidate:async()=>this.logger.warn(`Cannot invalidate transient "${i}"`)}}}buildContext(e,t,n,i,a){let o=e.key,s=t.scope===`transient`,{cleanupFunctions:c,disposeFunctions:l,capturedArtifactDeps:u,dependencyVersions:d,capturedStateSelectors:f}=a,p=async(e,t)=>{let r=t?this.computeParamKey(e,t):e;if(r===o)throw A(i);let a=this.graph.wouldCreateCycle(o,r);if(a)throw C(a);u.add(r);let s=await(t?this.resolveParameterized(e,t):this.build(e,n)),c=this.cache.get(r);return c&&d.set(r,c.version),s},m=t.scope===`singleton`?t.controller.signal:F,h=async(e,t)=>{let n=await p(e,t);if(n.error)throw n.error;return n.instance},g=(e,t)=>{let n=r(e);return f.push({paths:n,options:t}),e(this.store.get(!0))};return{state:()=>this.store.get(!0),previous:t.instance,signal:m,onCleanup:e=>c.push(e),onDispose:e=>l.push(e),use:e=>e({resolve:p,require:h,select:g}),stream:e=>{if(s)throw w(`Illegal stream on transient artifact "${i}"`);let n=t,r=async(e,t=void 0)=>{await n.streamSerializer.do(async()=>{n.stream!==void 0&&(n.instance=e,n.error=t,n.version++,this.cache.invalidatePackage(o),await this.processStream(i),this.events?.emit({name:`stream:emit`,payload:{key:i,value:e}}))})},a={value:()=>n.instance,get signal(){return n.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>r(e)};n.stream=async()=>{try{let t=await e(a);t&&n.cleanupFunctions.push(t)}catch(e){await r(void 0,e),await this.invalidate(o,!1,!0)}}}}}async runWithRetries(e,t,n){let r=t.signal,i=(e.retries??0)+1,o=0;for(;o<i;)try{if(r.aborted)throw new P;let a=e.factory(t),s;if(s=a instanceof Promise?e.timeout?await m(a,e.timeout):await a:a,r.aborted)throw new P;let c=this.detectStaleness(n);if(c){if(o++,n.clear(),o<i)continue;return{ok:!1,error:j(String(c))}}return{ok:!0,value:s}}catch(e){if(r.aborted||e instanceof P)throw new P;if(e instanceof a)throw e;if(o++,o>=i)return{ok:!1,error:e}}return{ok:!1,error:Error(`Build exhausted retry budget unexpectedly.`)}}commitResult(e,t,n,r,i){let{cleanupFunctions:a,disposeFunctions:o,capturedArtifactDeps:s,capturedStateSelectors:c}=i;n||(this.updateDependencyGraph(e,s,c),t.cleanupFunctions=a,t.disposeFunctions=o,t.artifactDependencies=new Set(s),t.stateGroups=c.map(({paths:e,options:t})=>({paths:e,options:t}))),r.ok?(t.instance=r.value,t.error=void 0):(t.instance=void 0,t.error=r.error),t.version++,this.cache.invalidatePackage(e)}detectStaleness(e){for(let[t,n]of e){let e=this.cache.get(t);if(e&&e.version!==n)return t}return null}async invalidate(e,t=!1,n=!1){let r=this.cache.get(e);if(!r)return;if(r.scope!==`singleton`)return this.executeInvalidation(e,t,n);let i=r;return i.debounceTimer&&=(clearTimeout(i.debounceTimer),void 0),!t&&i.activeDebounceMs>0?new Promise((r,a)=>{i.debounceTimer=setTimeout(()=>{i.debounceTimer=void 0,this.executeInvalidation(e,t,n).then(r).catch(a)},i.activeDebounceMs)}):this.executeInvalidation(e,t,n)}async executeInvalidation(e,t,n=!1){let r=this.cache.get(e);!r||r.scope!==`singleton`||await r.invalidationSerializer.do(async()=>{r.version++,await this.cache.invalidateInstance(e);let i=this.graph.iterDependents(e),a=i.size>0;await this.cascadeInvalidation(i),this.events?.emit({name:`artifact:invalidated`,payload:{key:e,cascade:a,replace:t}});let o=this.registry.get(e),s=o&&(t||!o.lazy||this.observer.hasWatchers(e))&&!n;s&&await this.build(e).catch(t=>{t instanceof P||this.logger.error(`Rebuild failed for "${String(e)}"`,t)}),(s||n)&&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),this.events?.emit({name:`artifact:disposed`,payload:{key:e}}))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(e.size===0)return;let t=[];for(let n of e)t.push(this.invalidate(n).catch(e=>{this.logger.error(`Cascade failed for "${String(n)}"`,e)}));await Promise.all(t)}updateDependencyGraph(e,t,n){let r=this.cache.get(e);if(!r||r.scope!==`singleton`)return;this.graph.registerNode(e),this.graph.setDependencies(e,t),r.stateDependencies=new Set;for(let{paths:e}of n)for(let t of e)r.stateDependencies.add(t);if(r.stateUnsubscribe&&=(r.stateUnsubscribe(),void 0),n.length===0)return;let i=()=>this.invalidate(e),a=new Map;for(let{paths:e,options:t}of n){let n=t===void 0?`undefined`:JSON.stringify(t),r=a.get(n);r||(r={options:t,paths:new Set},a.set(n,r));for(let t of e)r.paths.add(t)}let o=[];for(let{options:e,paths:t}of a.values()){if(t.size===0)continue;let n=Array.from(t);e===void 0?o.push(this.store.watch(n,i)):o.push(this.store.watch(n,i,e))}o.length===0?r.stateUnsubscribe=void 0:o.length===1?r.stateUnsubscribe=o[0]:r.stateUnsubscribe=()=>{for(let e of o)e()}}createCachedArtifact(n){return n.scope===`transient`?{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:n.debounce?n.debounce:0,controller:new AbortController,buildOnce:new e({retry:!0,throws:!0}),streamOnce:new e({retry:!0,throws:!0}),streamSerializer:new t({yieldMode:`microtask`}),invalidationSerializer:new t({yieldMode:`macrotask`}),stateGroups:[],artifactDependencies:new Set}}resolveStatic(e){if(!this.registry.getByString(e))throw S(e);return this.build(e)}async resolveParameterized(e,t){let n=this.registry.getByString(e);if(!n)throw S(String(e));if(!n.paramKey)throw O(String(e));let r=n.paramKey(t),i=this.registry.getByString(r);if(i&&!i.paramKey&&!i.virtual)throw k(String(e),r);return this.registry.hasString(r)||this.registry.setVirtual(r,{key:r,factory:e=>n.factory({...e,params:t}),scope:n.scope,lazy:n.lazy,timeout:n.timeout,retries:n.retries,debounce:n.debounce,virtual:!0}),this.build(r,void 0,e)}computeParamKey(e,t){let n=this.registry.getByString(e);if(!n||!n.paramKey)throw O(String(e));return n.paramKey(t)}},L=class{registry;cache;container;logger;listeners=new Map;watchers=new Map;constructor(e,t,n,r){this.registry=e,this.cache=t,this.container=n,this.logger=r}watch(e,t=60*1e3){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,n=60*1e3){let r=this.registry.get(e);if(!r.paramKey)throw Error(`Artifact "${String(e)}" is not parameterized.`);let i=r.paramKey(t);return this.watchForKey(i,r,n,t)}watchForKey(e,t,r,i){let a=t.scope===`transient`,o=a?f(e):e,s=this.watchers.get(o);if(s)return s.observer;let c=new n(async()=>{(a||i!==void 0)&&!this.registry.hasString(e)&&this.registry.setVirtual(e,{key:e,factory:a?t.factory:e=>t.factory({...e,params:i}),scope:a?`singleton`:t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})},async()=>{a||i!==void 0?(await this.registry.unregister(o).catch(()=>{}),this.cache.delete(o),this.watchers.delete(o)):this.cache.invalidatePackage(o),this.listeners.delete(o)},{gracePeriod:a&&i===void 0?`sync`:r}),l,u={id:o,get count(){return c.subscribers},get:(t=!1)=>c.subscribers===0&&!t?p:this.cache.package(o,(e,t)=>this.container.invalidate(o,e,t),e),resolve:()=>l||(l=(async()=>{await c.acquire();try{return await this.container.resolve(o)}finally{c.release(),l=void 0}})(),l),subscribe:(e,t=!0)=>{let n=()=>e(u.get());return c.acquire().then(()=>{this.container.resolve(o).then(()=>{this.listeners.has(o)||this.listeners.set(o,new Set),t&&n(),this.listeners.get(o).add(n)})}).catch(e=>{this.logger.error(`Resolution failed for "${o}"`,e),this.listeners.get(o)?.add(n)}),()=>{this.listeners.get(o)?.delete(n),c.release()}}};return this.watchers.set(o,{resource:c,observer:u}),u}evictWatcher(e){[e,f(e)].forEach(e=>{let t=this.watchers.get(e);t&&(t.resource.forceCleanup(),this.watchers.delete(e))})}notify(e){let t=this.listeners.get(e);if(!(!t||t.size===0))for(let n of t)try{n()}catch(t){this.logger.error(`Listener error for "${e}"`,t)}}hasWatchers(e){return this.watchers.has(e)||this.watchers.has(f(e))}getWatcherCount(e){return(this.watchers.get(e)||this.watchers.get(f(e)))?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}};let R=function(e){return e.Singleton=`singleton`,e.Transient=`transient`,e}({});var z=class{artifacts=new Map;register({key:e,factory:t,lazy:n,...r}){let{scope:i,...a}=r,o={key:e,factory:t,scope:r.scope??`singleton`,lazy:n===void 0?!0:n,...a};return this.artifacts.set(e,o),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw S(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()}},B=class n{registry;cache;graph;manager;observer;logger;store;events;constructor(e,t){this.logger=t?.logger??new l([new c],{module:`artifacts`}),this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t),subset:(...t)=>e.subset(...t)},this.events=s({errorHandler:e=>this.logger.error(`Lifecycle event error`,e)}),this.registry=new z,this.cache=new g,this.graph=new y,this.observer=new L(this.registry,this.cache,this,this.logger),this.manager=new I(this.registry,this.cache,this.graph,this.store,this.observer,this.logger,this.events)}debugInfo(){let e=[];return this.registry.keys().forEach(t=>{let n=t,r=this.registry.getByString(n),i=this.cache.get(n);if(!r)return;let a=`idle`;i&&(i.scope===`singleton`&&i.debounceTimer!==void 0?a=`debouncing`:i.scope===`singleton`&&i.buildOnce.running()?a=`building`:i.error?a=`error`:i.instance!==void 0&&(a=`active`)),e.push({id:n,scope:r.scope??`singleton`,status:a,dependencies:this.graph.getDependencies(n).map(e=>String(e)),dependents:this.graph.getDependents(n).map(e=>String(e)),stateDependencies:i?.scope===`singleton`?Array.from(i.stateDependencies):[],buildCount:i?.buildCount??0})}),e}register(e){let{key:t}=e,n=t;this.registry.has(t)&&(this.logger.warn(`Overwriting artifact "${n}".`),this.manager.dispose(t).catch(e=>{this.logger.error(`Failed to dispose existing artifact "${n}"`,e)})),this.registry.register(e),this.graph.registerNode(t);let r=e.scope??`singleton`,i=e.lazy??!0;return this.events.emit({name:`artifact:registered`,payload:{key:n,scope:r}}),!i&&r===`singleton`&&this.resolve(t).catch(e=>{this.logger.error(`Eager load failed for "${n}"`,e)}),()=>this.unregister(t)}has(e){return this.registry.has(e)}async unregister(e,t){let n=t===void 0?e:this.manager.computeParamKey(e,t);await this.manager.dispose(n),await this.registry.unregister(n),this.observer.evictWatcher(n)}async resolve(e,t){return t===void 0?this.manager.resolveStatic(e):this.manager.resolveParameterized(e,t)}async require(e,t){let n=await this.resolve(e,t);if(n.error)throw n.error;return n.instance}watch(e,t,n){return t===void 0?this.observer.watch(e,n):this.observer.watchParameterized(e,t,n)}peek(e,t){let n=t===void 0?e:this.manager.computeParamKey(e,t);return this.cache.get(n)?.instance}async invalidate(e,t){let n=t?.params,r=t?.replace??!1,i=n===void 0?e:this.manager.computeParamKey(e,n);return this.manager.invalidate(i,r)}on(e,t){return this.events.subscribe(e,t)}once(e,t){return this.events.once(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){let e=this.registry.keys();await Promise.allSettled(e.map(e=>this.manager.dispose(e).catch(t=>{this.logger.error(`Failed to dispose artifact "${String(e)}"`,t)}))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear(),this.events.emit({name:`container:dispose`,payload:{}}),this.events.clear({permanent:!0})}async export(){let e=[];for(let t of this.cache.keys()){let n=this.cache.get(t);if(!n||n.scope!==`singleton`||n.instance===void 0)continue;let r=new Set;for(let e of n.stateGroups)for(let t of e.paths)r.add(t);let i=Array.from(r).sort(),a=this.store.subset(i),o=await h(JSON.stringify(a,Object.keys(a).sort())),s;try{s=structuredClone(n.instance)}catch{throw N(t)}e.push({key:t,instance:s,state:{groups:n.stateGroups.map(e=>({paths:e.paths,options:e.options})),hash:o},dependencies:Array.from(n.artifactDependencies)})}let t={version:`1.0`,timestamp:Date.now(),artifacts:e},n=await h(JSON.stringify(t));return{...t,checksum:n}}async restore(n){let{checksum:r,...i}=n;if(await h(JSON.stringify(i))!==r)throw M(`Bundle checksum mismatch – data corrupted`);if(n.version!==`1.0`)throw M(`Unsupported bundle version: ${n.version}`);let a=new Map;for(let e of n.artifacts)a.set(e.key,e);let o=new Set,s=new Map;for(let e of n.artifacts)for(let t of e.dependencies)s.has(t)||s.set(t,new Set),s.get(t).add(e.key);let c=async e=>{let t=new Set;for(let n of e.state.groups)for(let e of n.paths)t.add(e);let n=Array.from(t).sort(),r=this.store.subset(n);return h(JSON.stringify(r,Object.keys(r).sort()))};for(let e of n.artifacts)await c(e)!==e.state.hash&&o.add(e.key);let l=Array.from(o);for(;l.length;){let e=l.shift(),t=s.get(e);if(t)for(let e of t)o.has(e)||(o.add(e),l.push(e))}for(let r of n.artifacts){if(o.has(r.key))continue;this.cache.get(r.key)&&await this.cache.invalidateInstance(r.key,!1);let n={scope:`singleton`,instance:r.instance,error:void 0,version:1,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set(r.state.groups.flatMap(e=>e.paths)),activeDebounceMs:0,buildOnce:new e({retry:!0,throws:!0}),streamSerializer:new t({yieldMode:`microtask`}),invalidationSerializer:new t({yieldMode:`macrotask`}),stateUnsubscribe:void 0,debounceTimer:void 0,controller:new AbortController,streamOnce:new e({retry:!0,throws:!0}),stream:void 0,stateGroups:r.state.groups,artifactDependencies:new Set(r.dependencies)};n.buildOnce.resolve(r.instance),this.cache.set(r.key,n);let i=[];for(let e of r.state.groups){let t=this.store.watch(e.paths,()=>this.invalidate(r.key),e.options);i.push(t)}n.stateUnsubscribe=()=>{for(let e of i)e()},this.graph.setDependencies(r.key,r.dependencies)}}static async from(e){let t=new n(e.store,{logger:e.logger});if(e.bundle){if(typeof e.bundle!=`object`||!e.bundle.version||!Array.isArray(e.bundle.artifacts))throw M(`Invalid bundle: missing version or artifacts array`);await t.restore(e.bundle)}for(let n of e.templates)t.register(n);return t}};export{B as ArtifactContainer,R as ArtifactScopes,b as ErrorCodes,P as SupersededBuildError,a as SystemError,S as artifactNotFound,j as buildStaleAfterRetries,C as cycleDetected,w as illegalScope,N as invalidExport,M as invalidImport,D as keyConflict,O as notParameterized,k as paramKeyCollision,A as selfDependency,E as timeoutError,T as watcherDisposed};
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "@asaidimu/utils-artifacts",
3
- "version": "8.2.12",
3
+ "version": "8.2.14",
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.0.0",
9
+ "@asaidimu/utils-events": "^1.2.3",
10
10
  "@asaidimu/utils-error": "^1.0.0",
11
- "@asaidimu/utils-logger": "^1.0.4"
11
+ "@asaidimu/utils-logger": "^1.0.5",
12
+ "@asaidimu/utils-sync": "^2.3.2",
13
+ "@asaidimu/utils-store": "^10.2.7"
12
14
  },
13
15
  "keywords": [
14
16
  "typescript",
@@ -63,5 +65,6 @@
63
65
  }
64
66
  ]
65
67
  ]
66
- }
68
+ },
69
+ "peerDependencies": {}
67
70
  }