@asaidimu/utils-artifacts 1.0.0 → 2.0.1
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/README.md +103 -139
- package/index.d.mts +118 -274
- package/index.d.ts +118 -274
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -90,59 +90,6 @@ interface DataStore<T extends object> {
|
|
|
90
90
|
state(): Readonly<StoreExecutionState<T>>;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
/**
|
|
94
|
-
* Represents all errors within the ArtifactContainer system, categorized
|
|
95
|
-
* into "system" (internal structural), "external" (runtime failures),
|
|
96
|
-
* or "cycle" (circular dependencies). This unified error class simplifies
|
|
97
|
-
* error handling and provides clear semantics.
|
|
98
|
-
*/
|
|
99
|
-
declare class ArtifactError extends Error {
|
|
100
|
-
category: "system" | "external";
|
|
101
|
-
constructor(message: string, category: "system" | "external", cause?: unknown);
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Error thrown when a circular dependency is detected during artifact resolution.
|
|
105
|
-
* This indicates a structural problem in the artifact graph.
|
|
106
|
-
*/
|
|
107
|
-
declare class CircularDependencyError extends ArtifactError {
|
|
108
|
-
/**
|
|
109
|
-
* Creates an instance of CircularDependencyError.
|
|
110
|
-
* @param path The dependency path that caused the cycle.
|
|
111
|
-
*/
|
|
112
|
-
constructor(path: string[]);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Error thrown when an artifact requested for resolution is not found
|
|
116
|
-
* within the current container or its parent hierarchy.
|
|
117
|
-
*/
|
|
118
|
-
declare class ArtifactNotFoundError extends ArtifactError {
|
|
119
|
-
/**
|
|
120
|
-
* Creates an instance of ArtifactNotFoundError.
|
|
121
|
-
* @param key The key of the artifact that was not found.
|
|
122
|
-
*/
|
|
123
|
-
constructor(key: string);
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Error thrown when an operation is attempted that is not permitted
|
|
127
|
-
* due to the artifact's scope or current state (e.g., calling `yield` on a Transient artifact).
|
|
128
|
-
*/
|
|
129
|
-
declare class IllegalScopeError extends ArtifactError {
|
|
130
|
-
/**
|
|
131
|
-
* Creates an instance of IllegalScopeError.
|
|
132
|
-
* @param message A descriptive message about the illegal operation.
|
|
133
|
-
*/
|
|
134
|
-
constructor(message: string);
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Error returned when all a watched instance is disposed
|
|
138
|
-
*/
|
|
139
|
-
declare class WatcherDisposedError extends ArtifactError {
|
|
140
|
-
/**
|
|
141
|
-
* Creates an instance of IllegalScopeError.
|
|
142
|
-
* @param message A descriptive message about the illegal operation.
|
|
143
|
-
*/
|
|
144
|
-
constructor(key: string);
|
|
145
|
-
}
|
|
146
93
|
/**
|
|
147
94
|
* Defines the lifecycle and sharing strategy for an artifact.
|
|
148
95
|
*/
|
|
@@ -161,50 +108,6 @@ declare enum ArtifactScopes {
|
|
|
161
108
|
Singleton = "singleton",
|
|
162
109
|
Transient = "transient"
|
|
163
110
|
}
|
|
164
|
-
/**
|
|
165
|
-
* Configuration options for defining an artifact. These options control
|
|
166
|
-
* its lifecycle, instantiation, and error handling behavior.
|
|
167
|
-
*/
|
|
168
|
-
interface ArtifactOptions {
|
|
169
|
-
/**
|
|
170
|
-
* The scope of the artifact, determining its lifecycle and sharing strategy.
|
|
171
|
-
* Defaults to `ArtifactScopes.Singleton`.
|
|
172
|
-
*/
|
|
173
|
-
scope?: ArtifactScope;
|
|
174
|
-
/**
|
|
175
|
-
* If `true` (default), the artifact's factory is executed only when the artifact
|
|
176
|
-
* is first requested. If `false`, the artifact is built immediately upon registration
|
|
177
|
-
* (only applies to Singleton scopes).
|
|
178
|
-
*/
|
|
179
|
-
lazy?: boolean;
|
|
180
|
-
/**
|
|
181
|
-
* Maximum time in milliseconds allowed for the artifact's factory function
|
|
182
|
-
* to complete execution. If exceeded, the factory will time out.
|
|
183
|
-
*/
|
|
184
|
-
timeoutMs?: number;
|
|
185
|
-
/**
|
|
186
|
-
* Number of times to retry the artifact's factory on failure due to an
|
|
187
|
-
* external (runtime) error. SystemErrors are not retried. Defaults to `0`.
|
|
188
|
-
*/
|
|
189
|
-
retries?: number;
|
|
190
|
-
/**
|
|
191
|
-
* Base debounce time in milliseconds for invalidation events originating
|
|
192
|
-
* from this artifact. This can be overridden by `UseOptions.debounce`.
|
|
193
|
-
*/
|
|
194
|
-
debounce?: number;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Options that can be applied to dependency resolutions within an artifact's factory,
|
|
198
|
-
* allowing for fine-grained control over how dependencies affect the current artifact.
|
|
199
|
-
*/
|
|
200
|
-
interface UseOptions {
|
|
201
|
-
/**
|
|
202
|
-
* Applies a specific debounce time in milliseconds to dependencies resolved
|
|
203
|
-
* within the `use` block. If this value is higher than the artifact's
|
|
204
|
-
* `baseDebounceMs` (or `activeDebounceMs`), it will be used for subsequent invalidations.
|
|
205
|
-
*/
|
|
206
|
-
debounce?: number;
|
|
207
|
-
}
|
|
208
111
|
/**
|
|
209
112
|
* Represents a snapshot of an artifact's state and dependencies for debugging purposes.
|
|
210
113
|
* Provides insight into the artifact's current status and its position within the dependency graph.
|
|
@@ -259,6 +162,11 @@ interface UseDependencyContext<TRegistry extends Record<string, any>, TState ext
|
|
|
259
162
|
*/
|
|
260
163
|
select<S>(selector: (state: TState) => S): S;
|
|
261
164
|
}
|
|
165
|
+
type ArtifactStreamContext<TArtifact> = {
|
|
166
|
+
value: TArtifact | undefined;
|
|
167
|
+
signal: AbortSignal;
|
|
168
|
+
emit: (value: TArtifact) => Promise<void>;
|
|
169
|
+
};
|
|
262
170
|
/**
|
|
263
171
|
* The full context provided to an artifact's factory function.
|
|
264
172
|
* This context allows the artifact to interact with the container,
|
|
@@ -289,7 +197,7 @@ interface ArtifactFactoryContext<TRegistry extends Record<string, any>, TState e
|
|
|
289
197
|
* @param options Optional settings for this dependency block, like debounce.
|
|
290
198
|
* @returns A Promise resolving to the result of the callback.
|
|
291
199
|
*/
|
|
292
|
-
use<R>(callback: (ctx: UseDependencyContext<TRegistry, TState>) => R | Promise<R
|
|
200
|
+
use<R>(callback: (ctx: UseDependencyContext<TRegistry, TState>) => R | Promise<R>): Promise<R>;
|
|
293
201
|
/**
|
|
294
202
|
* Registers a cleanup function to be executed when the artifact is
|
|
295
203
|
* invalidated and before its new instance is built. This is useful
|
|
@@ -313,7 +221,7 @@ interface ArtifactFactoryContext<TRegistry extends Record<string, any>, TState e
|
|
|
313
221
|
* @throws {SystemError} if called on a Transient artifact, as Transient artifacts
|
|
314
222
|
* do not maintain a persistent value.
|
|
315
223
|
*/
|
|
316
|
-
|
|
224
|
+
stream(callback: (ctx: ArtifactStreamContext<TArtifact>) => void | Promise<void>): void;
|
|
317
225
|
}
|
|
318
226
|
/**
|
|
319
227
|
* A function that performs cleanup logic for an artifact, potentially asynchronously.
|
|
@@ -363,7 +271,7 @@ type ArtifactFactory<TRegistry extends Record<string, any>, TState extends objec
|
|
|
363
271
|
* Provides a way to get the current resolved artifact and subscribe to updates.
|
|
364
272
|
* @template TArtifact The type of the artifact being watched.
|
|
365
273
|
*/
|
|
366
|
-
interface
|
|
274
|
+
interface ArtifactObserver<TArtifact> {
|
|
367
275
|
/** The unique identifier (key) of the artifact being watched. */
|
|
368
276
|
id: string;
|
|
369
277
|
/**
|
|
@@ -382,7 +290,7 @@ interface ArtifactWatcher<TArtifact> {
|
|
|
382
290
|
* @param callback The function to call on updates.
|
|
383
291
|
* @returns A function to unsubscribe the callback.
|
|
384
292
|
*/
|
|
385
|
-
subscribe(callback: () => void): () => void;
|
|
293
|
+
subscribe(callback: (artifact: ResolvedArtifact<TArtifact>) => void): () => void;
|
|
386
294
|
/**
|
|
387
295
|
* Disposes of this watcher reference, decrementing the reference count.
|
|
388
296
|
* When the count reaches zero, cleans up all associated resources.
|
|
@@ -396,218 +304,154 @@ interface ArtifactWatcher<TArtifact> {
|
|
|
396
304
|
* depends on another or is depended upon by another, potentially across
|
|
397
305
|
* different `ArtifactContainer` instances (e.g., parent/child containers).
|
|
398
306
|
*/
|
|
399
|
-
interface DependencyLink {
|
|
307
|
+
interface DependencyLink<T> {
|
|
400
308
|
/** The key of the artifact involved in the dependency. */
|
|
401
309
|
key: string;
|
|
402
310
|
/** The `ArtifactContainer` instance that owns the linked artifact. */
|
|
403
|
-
container:
|
|
311
|
+
container: T;
|
|
404
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* Configuration options for defining an artifact. These options control
|
|
315
|
+
* its lifecycle, instantiation, and error handling behavior.
|
|
316
|
+
*/
|
|
317
|
+
interface ArtifactTemplate<TRegistry extends Record<string, any>, TState extends object, K extends keyof TRegistry> {
|
|
318
|
+
/** The unique key identifying this artifact. */
|
|
319
|
+
key: K;
|
|
320
|
+
/** The factory function responsible for creating the artifact's instance. */
|
|
321
|
+
factory: ArtifactFactory<TRegistry, TState, K>;
|
|
322
|
+
/**
|
|
323
|
+
* The scope of the artifact, determining its lifecycle and sharing strategy.
|
|
324
|
+
* Defaults to `ArtifactScopes.Singleton`.
|
|
325
|
+
*/
|
|
326
|
+
scope?: ArtifactScope;
|
|
327
|
+
/**
|
|
328
|
+
* If `true` (default), the artifact's factory is executed only when the artifact
|
|
329
|
+
* is first requested. If `false`, the artifact is built immediately upon registration
|
|
330
|
+
* (only applies to Singleton scopes).
|
|
331
|
+
*/
|
|
332
|
+
lazy?: boolean;
|
|
333
|
+
/**
|
|
334
|
+
* Maximum time in milliseconds allowed for the artifact's factory function
|
|
335
|
+
* to complete execution. If exceeded, the factory will time out.
|
|
336
|
+
*/
|
|
337
|
+
timeout?: number;
|
|
338
|
+
/**
|
|
339
|
+
* Number of times to retry the artifact's factory on failure due to an
|
|
340
|
+
* external (runtime) error. SystemErrors are not retried. Defaults to `0`.
|
|
341
|
+
*/
|
|
342
|
+
retries?: number;
|
|
343
|
+
/**
|
|
344
|
+
* Base debounce time in milliseconds for invalidation events originating
|
|
345
|
+
* from this artifact. This can be overridden by `UseOptions.debounce`.
|
|
346
|
+
*/
|
|
347
|
+
debounce?: number;
|
|
348
|
+
}
|
|
349
|
+
|
|
405
350
|
/**
|
|
406
351
|
* A dependency injection container for managing the lifecycle, dependencies,
|
|
407
352
|
* and instances of "artifacts" (any JavaScript/TypeScript object or value).
|
|
408
|
-
* It supports hierarchical containers, different scopes (singleton, transient),
|
|
409
|
-
* dependency resolution, state-based invalidation, and debounced rebuilding.
|
|
410
353
|
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
354
|
+
* Refactored to separate concerns:
|
|
355
|
+
* - ArtifactRegistry: Stores artifact templates (factories + options)
|
|
356
|
+
* - ArtifactCache: Stores resolved singleton instances
|
|
357
|
+
* - ArtifactDependencyGraph: Tracks artifact dependencies using DependencyGraph
|
|
358
|
+
* - ArtifactManager: Handles lifecycle (build, invalidate, dispose)
|
|
359
|
+
* - ArtifactObserver: Manages watchers and subscriptions
|
|
360
|
+
*
|
|
361
|
+
* @template TRegistry A type that maps artifact keys to their types
|
|
362
|
+
* @template TState The type of the global state object
|
|
415
363
|
*/
|
|
416
364
|
declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<string, any>, TState extends object = any> {
|
|
417
|
-
private readonly
|
|
418
|
-
private readonly
|
|
419
|
-
private readonly
|
|
420
|
-
private readonly
|
|
421
|
-
private readonly
|
|
422
|
-
private readonly
|
|
423
|
-
private isDisposed;
|
|
424
|
-
private resolvedArtifacts;
|
|
365
|
+
private readonly registry;
|
|
366
|
+
private readonly cache;
|
|
367
|
+
private readonly graph;
|
|
368
|
+
private readonly manager;
|
|
369
|
+
private readonly observer;
|
|
370
|
+
private readonly store;
|
|
425
371
|
/**
|
|
426
372
|
* Creates a new ArtifactContainer instance.
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
* @param parent An optional parent `ArtifactContainer`. If provided, this container
|
|
430
|
-
* can resolve artifacts registered in its parent.
|
|
431
|
-
*/
|
|
432
|
-
constructor(store: Pick<DataStore<TState>, "watch" | "get">, parent?: ArtifactContainer<TRegistry, TState>);
|
|
433
|
-
/**
|
|
434
|
-
* Creates a new child `ArtifactContainer` that inherits from the current container.
|
|
435
|
-
* Child containers can resolve artifacts registered in their parent, but
|
|
436
|
-
* artifacts registered in the child are local to that child.
|
|
437
|
-
* @returns A new `ArtifactContainer` instance.
|
|
373
|
+
*
|
|
374
|
+
* @param store An object providing functions to interact with a global data store
|
|
438
375
|
*/
|
|
439
|
-
|
|
376
|
+
constructor(store: Pick<DataStore<TState>, "watch" | "get">);
|
|
440
377
|
/**
|
|
441
378
|
* Provides debug information about all artifacts currently registered in this container.
|
|
442
|
-
*
|
|
443
|
-
* @returns An array of
|
|
379
|
+
*
|
|
380
|
+
* @returns An array of ArtifactDebugNode objects
|
|
444
381
|
*/
|
|
445
|
-
|
|
382
|
+
debugInfo(): ArtifactDebugNode[];
|
|
446
383
|
/**
|
|
447
384
|
* Registers a new artifact with the container.
|
|
448
385
|
* If an artifact with the same key already exists, it will be overwritten and disposed.
|
|
449
386
|
* For Singleton, non-lazy artifacts, the factory will be immediately invoked.
|
|
450
|
-
*
|
|
451
|
-
* @param
|
|
452
|
-
* @
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
* @returns A cleanup function that, when called, unregisters the artifact.
|
|
456
|
-
*/
|
|
457
|
-
register<K extends keyof TRegistry>({ key, factory, ...options }: {
|
|
458
|
-
key: K;
|
|
459
|
-
factory: ArtifactFactory<TRegistry, TState, K>;
|
|
460
|
-
} & ArtifactOptions): () => void;
|
|
387
|
+
*
|
|
388
|
+
* @param params The registration parameters
|
|
389
|
+
* @returns A cleanup function that unregisters the artifact
|
|
390
|
+
*/
|
|
391
|
+
register<K extends keyof TRegistry>(params: ArtifactTemplate<TRegistry, TState, K>): () => void;
|
|
461
392
|
/**
|
|
462
393
|
* Unregisters an artifact from the container, disposing of its current instance
|
|
463
394
|
* and removing all associated resources and dependency links.
|
|
464
|
-
*
|
|
465
|
-
* @param key The unique identifier of the artifact
|
|
466
|
-
* @returns A Promise that resolves when the artifact has been fully unregistered and disposed.
|
|
395
|
+
*
|
|
396
|
+
* @param key The unique identifier of the artifact
|
|
467
397
|
*/
|
|
468
398
|
unregister<K extends keyof TRegistry>(key: K): Promise<void>;
|
|
469
399
|
/**
|
|
470
400
|
* Resolves an artifact by its key, returning its instance or an error.
|
|
471
|
-
* This method handles dependency resolution, cycle detection
|
|
472
|
-
* and retry logic.
|
|
401
|
+
* This method handles dependency resolution, cycle detection (via graph),
|
|
402
|
+
* caching, and retry logic. Traverses the container hierarchy if the artifact
|
|
473
403
|
* is not found locally.
|
|
474
|
-
*
|
|
475
|
-
* @param key The unique identifier for the artifact
|
|
476
|
-
* @returns A Promise that resolves to a
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
* @throws {CircularDependencyError} if a circular dependency is detected during resolution.
|
|
480
|
-
* @throws {ArtifactNotFoundError} if the artifact with the given key is not found
|
|
481
|
-
* in the current container or any parent containers.
|
|
482
|
-
* @throws {SystemError} for any other critical structural or configuration issues.
|
|
404
|
+
*
|
|
405
|
+
* @param key The unique identifier for the artifact
|
|
406
|
+
* @returns A Promise that resolves to a ResolvedArtifact
|
|
407
|
+
* @throws {ArtifactNotFoundError} if the artifact is not found
|
|
408
|
+
* @throws {ArtifactError} if a cycle is detected or other system errors occur
|
|
483
409
|
*/
|
|
484
410
|
resolve<K extends keyof TRegistry>(key: K): Promise<ResolvedArtifact<TRegistry[K]>>;
|
|
485
411
|
/**
|
|
486
|
-
* Returns an
|
|
487
|
-
* The watcher allows subscribing to changes in the artifact's resolved value
|
|
488
|
-
*
|
|
489
|
-
* @param key The unique identifier for the artifact
|
|
490
|
-
* @returns An
|
|
412
|
+
* Returns an ArtifactWatcher for a given artifact key.
|
|
413
|
+
* The watcher allows subscribing to changes in the artifact's resolved value.
|
|
414
|
+
*
|
|
415
|
+
* @param key The unique identifier for the artifact
|
|
416
|
+
* @returns An ArtifactWatcher instance
|
|
491
417
|
*/
|
|
492
|
-
watch<K extends keyof TRegistry>(key: K):
|
|
418
|
+
watch<K extends keyof TRegistry>(key: K): ArtifactObserver<TRegistry[K]>;
|
|
493
419
|
/**
|
|
494
420
|
* Peeks at the resolved instance of an artifact without triggering its resolution
|
|
495
|
-
* if it's lazy, or registering a dependency.
|
|
496
|
-
*
|
|
497
|
-
* @
|
|
498
|
-
* @
|
|
499
|
-
* @returns The artifact instance if it's already built, otherwise `undefined`.
|
|
421
|
+
* if it's lazy, or registering a dependency.
|
|
422
|
+
*
|
|
423
|
+
* @param key The unique identifier for the artifact
|
|
424
|
+
* @returns The artifact instance if it's already built, otherwise undefined
|
|
500
425
|
*/
|
|
501
426
|
peek<K extends keyof TRegistry>(key: K): TRegistry[K] | undefined;
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
*
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
* @param
|
|
521
|
-
* @returns
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
* Handles the propagation of a `yield` event from a Singleton artifact.
|
|
527
|
-
* This involves invalidating all direct dependents and notifying any listeners.
|
|
528
|
-
* @param key The key of the artifact that yielded a new value.
|
|
529
|
-
*/
|
|
530
|
-
private processYieldPropagation;
|
|
531
|
-
/**
|
|
532
|
-
* Registers a dependency from a `dependent` artifact on a `target` artifact.
|
|
533
|
-
* This builds the inverse dependency graph, allowing for efficient cascade invalidations.
|
|
534
|
-
* This method is public so that child containers can register dependents on artifacts
|
|
535
|
-
* owned by a parent container.
|
|
536
|
-
* @param targetKey The key of the artifact being depended upon.
|
|
537
|
-
* @param dependentKey The key of the artifact that depends on the target.
|
|
538
|
-
* @param dependentContainer The container instance where the dependent artifact is registered.
|
|
539
|
-
*/
|
|
540
|
-
registerDependent(targetKey: string, dependentKey: string, dependentContainer: ArtifactContainer<any, any>): void;
|
|
541
|
-
/**
|
|
542
|
-
* Removes a previously registered dependency link.
|
|
543
|
-
* This method is public so that child containers can remove dependents on artifacts
|
|
544
|
-
* owned by a parent container when their artifacts are disposed.
|
|
545
|
-
* @param targetKey The key of the artifact that was depended upon.
|
|
546
|
-
* @param dependentKey The key of the artifact that previously depended on the target.
|
|
547
|
-
* @param dependentContainer The container instance where the dependent artifact was registered.
|
|
548
|
-
*/
|
|
549
|
-
removeDependent(targetKey: string, dependentKey: string, dependentContainer: ArtifactContainer<any, any>): void;
|
|
550
|
-
/**
|
|
551
|
-
* Initiates the invalidation process for an artifact, potentially debouncing the rebuild.
|
|
552
|
-
* Invalidation marks an artifact as needing to be rebuilt on its next resolution.
|
|
553
|
-
* @template K The key of the artifact to invalidate.
|
|
554
|
-
* @param key The unique identifier for the artifact.
|
|
555
|
-
* @param replace If `true`, bypasses debouncing and forces an immediate execution of `executeInvalidation`.
|
|
556
|
-
* @returns A Promise that resolves when the invalidation (and potential debounced rebuild) is complete.
|
|
557
|
-
*/
|
|
558
|
-
private invalidate;
|
|
559
|
-
/**
|
|
560
|
-
* Executes the actual invalidation and rebuild logic for an artifact.
|
|
561
|
-
* This includes disposing the old instance, invalidating dependents, and (optionally) resolving a new instance.
|
|
562
|
-
* @template K The key of the artifact to invalidate.
|
|
563
|
-
* @param key The unique identifier for the artifact.
|
|
564
|
-
* @param replace If `true`, forces immediate disposal and rebuild without waiting for existing rebuild promises.
|
|
565
|
-
* @returns A Promise that resolves when the invalidation and rebuild process is complete.
|
|
566
|
-
*/
|
|
567
|
-
private executeInvalidation;
|
|
568
|
-
/**
|
|
569
|
-
* Disposes of an artifact's instance by running its cleanup and dispose functions,
|
|
570
|
-
* unsubscribing from state changes, and clearing its cached instance and error.
|
|
571
|
-
* This prepares the artifact for a rebuild or removal.
|
|
572
|
-
* @param def The `ArtifactDefinition` of the instance to dispose.
|
|
573
|
-
*/
|
|
574
|
-
private disposeInstance;
|
|
575
|
-
/**
|
|
576
|
-
* Fully disposes of an artifact, including its instance and all its associated
|
|
577
|
-
* dependency graph links and resources. This is typically called when an artifact
|
|
578
|
-
* is unregistered or the container itself is disposed.
|
|
579
|
-
* @param key The unique identifier of the artifact to dispose.
|
|
580
|
-
*/
|
|
581
|
-
private disposeArtifact;
|
|
582
|
-
/**
|
|
583
|
-
* Updates the dependency graph for an artifact based on newly discovered dependencies
|
|
584
|
-
* during its factory execution. This involves adding and removing dependent links,
|
|
585
|
-
* and setting up or tearing down state subscriptions.
|
|
586
|
-
* @param def The `ArtifactDefinition` whose graph is being updated.
|
|
587
|
-
* @param newArtifactDeps The set of artifact dependencies discovered during the latest build.
|
|
588
|
-
* @param newStateDeps The set of state path dependencies discovered during the latest build.
|
|
589
|
-
*/
|
|
590
|
-
private updateGraph;
|
|
591
|
-
/**
|
|
592
|
-
* Creates a single composite cleanup function from an array of individual cleanup functions.
|
|
593
|
-
* The composite function executes all provided cleanups in reverse order of registration,
|
|
594
|
-
* ensuring proper resource release, and handles potential asynchronous cleanups.
|
|
595
|
-
* @param fns An array of `ArtifactCleanup` functions.
|
|
596
|
-
* @returns A composite `ArtifactCleanup` function, or `undefined` if the array is empty.
|
|
597
|
-
*/
|
|
598
|
-
private createCompositeCleanup;
|
|
599
|
-
/**
|
|
600
|
-
* Notifies all registered listeners (watchers) for a specific artifact that
|
|
601
|
-
* its state (instance or error) has potentially changed.
|
|
602
|
-
* @param key The key of the artifact whose listeners should be notified.
|
|
603
|
-
*/
|
|
604
|
-
private notifyListeners;
|
|
605
|
-
/**
|
|
606
|
-
* Disposes of the entire `ArtifactContainer` and all artifacts registered within it.
|
|
427
|
+
/**
|
|
428
|
+
* Invalidates an artifact, triggering rebuild and cascade to dependents.
|
|
429
|
+
*
|
|
430
|
+
* @param key The artifact key to invalidate
|
|
431
|
+
* @param replace If true, forces immediate rebuild bypassing debounce
|
|
432
|
+
*/
|
|
433
|
+
invalidate<K extends keyof TRegistry>(key: K, replace?: boolean): Promise<void>;
|
|
434
|
+
/**
|
|
435
|
+
* Notifies observers that an artifact has changed.
|
|
436
|
+
* Called by ArtifactManager during stream propagation.
|
|
437
|
+
*
|
|
438
|
+
* @param key The artifact key
|
|
439
|
+
*/
|
|
440
|
+
notifyObservers(key: string): void;
|
|
441
|
+
/**
|
|
442
|
+
* Checks if an artifact has active watchers.
|
|
443
|
+
* Called by ArtifactManager to determine if lazy artifacts should rebuild.
|
|
444
|
+
*
|
|
445
|
+
* @param key The artifact key
|
|
446
|
+
* @returns True if the artifact has active watchers
|
|
447
|
+
*/
|
|
448
|
+
hasWatchers(key: string): boolean;
|
|
449
|
+
/**
|
|
450
|
+
* Disposes of the entire ArtifactContainer and all artifacts registered within it.
|
|
607
451
|
* This releases all resources, stops all watchers, and clears all internal state.
|
|
608
452
|
* After disposal, the container should no longer be used.
|
|
609
453
|
*/
|
|
610
454
|
dispose(): void;
|
|
611
455
|
}
|
|
612
456
|
|
|
613
|
-
export { type ArtifactCleanup, ArtifactContainer, type ArtifactDebugNode,
|
|
457
|
+
export { type ArtifactCleanup, ArtifactContainer, type ArtifactDebugNode, type ArtifactFactory, type ArtifactFactoryContext, type ArtifactObserver, type ArtifactScope, ArtifactScopes, type ArtifactStreamContext, type ArtifactTemplate, type DependencyLink, type ResolvedArtifact, type UseDependencyContext };
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t,r=Object.create,n=Object.defineProperty,i=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,c=(e={"src/store/node_modules/@asaidimu/events/index.js"(e,t){var r,n=Object.defineProperty,i=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o={};((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})(o,{createEventBus:()=>c}),t.exports=(r=o,((e,t,r,o)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of s(t))a.call(e,c)||c===r||n(e,c,{get:()=>t[c],enumerable:!(o=i(t,c))||o.enumerable});return e})(n({},"__esModule",{value:!0}),r));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let r=[],n=0,i=0;const s=new Map,a=new Map;let o=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?o=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{n++,i+=t,s.set(e,(s.get(e)||0)+1)},l=()=>{const t=r;r=[],t.forEach((({name:t,payload:r})=>{const n=performance.now();try{(a.get(t)||[]).forEach((e=>e(r)))}catch(n){e.errorHandler({...n,eventName:t,payload:r})}c(t,performance.now()-n)}))},d=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),p=e=>{const r=t.get(e);r?a.set(e,Array.from(r)):a.delete(e)};return o&&(o.onmessage=e=>{const{name:t,payload:r}=e.data;(a.get(t)||[]).forEach((e=>e(r)))}),{subscribe:(e,r)=>{t.has(e)||t.set(e,new Set);const n=t.get(e);return n.add(r),p(e),()=>{n.delete(r),0===n.size?(t.delete(e),a.delete(e)):p(e)}},emit:({name:t,payload:n})=>{if(e.async)return r.push({name:t,payload:n}),r.length>=e.batchSize?l():d(),void(o&&o.postMessage({name:t,payload:n}));const i=performance.now();try{(a.get(t)||[]).forEach((e=>e(n))),o&&o.postMessage({name:t,payload:n})}catch(r){e.errorHandler({...r,eventName:t,payload:n})}c(t,performance.now()-i)},getMetrics:()=>({totalEvents:n,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:s,averageEmitDuration:n>0?i/n:0}),clear:()=>{t.clear(),a.clear(),r=[],n=0,i=0,s.clear(),o&&(o.close(),o=null)}}}}},function(){return t||(0,e[s(e)[0]])((t={exports:{}}).exports,t),t.exports});((e,t,c)=>{c=null!=e?r(a(e)):{},((e,t,r,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of s(t))o.call(e,c)||c===r||n(e,c,{get:()=>t[c],enumerable:!(a=i(t,c))||a.enumerable})})(e&&e.__esModule?c:n(c,"default",{value:e,enumerable:!0}),e)})(c());var l=class e extends Error{category;constructor(t,r,n){super(t,{cause:n}),this.name="ArtifactError",this.category=r,Object.setPrototypeOf(this,e.prototype)}},d=class extends l{constructor(e){super(`[ArtifactContainer] Cycle detected: ${e.join(" -> ")}`,"system")}},p=class extends l{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system")}},u=class extends l{constructor(e){super(`[ArtifactContainer] Artifact ${e} has already been disposed`,"system")}},h=(e=>(e.Singleton="singleton",e.Transient="transient",e))(h||{});exports.ArtifactContainer=class e{artifacts=new Map;resolvingStack=[];listeners=new Map;watcherCache=new Map;props;parent;isDisposed=!1;resolvedArtifacts=new Map;constructor(e,t){this.props={watch:(...t)=>e.watch(...t),get:()=>e.get(!0)},this.parent=t}createChild(){return new e(this.props,this)}getDebugInfo(){const e=[];return this.artifacts.forEach(((t,r)=>{e.push({id:r,scope:t.scope,status:t.initializationPromise||t.rebuildPromise?"pending":t.error?"error":t.instance?"active":"idle",dependencies:Array.from(t.artifactDependencies).map((e=>e.key)),dependents:Array.from(t.dependents).map((e=>e.key)),stateDependencies:Array.from(t.stateDependencies),renderCount:t.buildCount})})),e}register({key:e,factory:t,...r}){const n=e;this.artifacts.has(n)&&(console.warn(`[ArtifactContainer] Overwriting "${n}".`),this.disposeArtifact(n));const i={key:e,factory:t,scope:r.scope??"singleton",lazy:r.lazy??!0,timeoutMs:r.timeoutMs,retries:r.retries??0,baseDebounceMs:r.debounce??0,activeDebounceMs:r.debounce??0,isInvalidationScheduled:!1,cleanupFunctions:[],disposeFunctions:[],stateDependencies:new Set,artifactDependencies:new Set,dependents:new Set,buildCount:0};return this.artifacts.set(n,i),i.lazy||"singleton"!==i.scope||this.resolve(e).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${n}":`,e)})),()=>this.unregister(e)}async unregister(e){const t=e;this.artifacts.has(t)&&(await this.disposeArtifact(t),this.artifacts.delete(t))}async resolve(e){const t=e,{def:r,container:n}=this.findDefinition(t)||{};if(!r||!n){if(this.parent)return this.parent.resolve(e);throw new p(t)}if("singleton"===r.scope&&r.initializationPromise){try{await r.initializationPromise}catch(e){}finally{r.initializationPromise=void 0}return this.packageArtifact(r)}if(this.resolvingStack.includes(t))throw new d([...this.resolvingStack,t]);if(n!==this)return n.resolve(e);const i="transient"===r.scope?(new Date).toISOString():e;this.resolvingStack.push(i);try{if("transient"===r.scope){const e=await this.createArtifactInstance(r,new Set,new Set);return{instance:e.instance,cleanup:e.cleanup,error:e.error,ready:!0,invalidate:async()=>console.warn(`[ArtifactContainer] Cannot invalidate transient "${t}"`)}}if(void 0!==r.instance||void 0!==r.error)return this.packageArtifact(r);const e=(async()=>{try{const e=new Set,t=new Set,n=await this.createArtifactInstance(r,e,t);this.updateGraph(r,e,t),n.error?r.error=n.error:r.instance=n.instance}catch(e){if(e instanceof l)throw e;r.error=e}finally{r.initializationPromise=void 0}})();return r.initializationPromise=e,await e,this.packageArtifact(r)}finally{this.resolvingStack.pop()}}watch(e){const t=e,r=this.findDefinition(t);if(!r){if(this.parent)return this.parent.watch(e);throw new p(t)}const{def:n,container:i}=r;if(i!==this)return i.watch(e);let s=t;if("transient"===n.scope&&(s=`${t}__watched`),this.watcherCache.has(s)){const e=this.watcherCache.get(s);return e.count++,e}"transient"!==n.scope||this.findDefinition(s)||this.register({key:s,factory:n.factory,scope:"singleton",lazy:n.lazy,timeoutMs:n.timeoutMs,retries:n.retries,debounce:n.baseDebounceMs});let a=!1;const o={id:t,count:1,get:()=>{const e=this.artifacts.get(s);if(!e)throw new p(s);const r=this.packageArtifact(e);return a&&(r.ready=!1,r.instance=void 0,r.invalidate=e=>Promise.resolve(),r.cleanup=()=>{},r.error=new u(t)),r},subscribe:e=>this.isDisposed?()=>{}:(this.listeners.has(s)||this.listeners.set(s,new Set),this.listeners.get(s).add(e),this.resolve(s).catch((e=>{console.error(`[ArtifactContainer] Background resolution failed for "${s}":`,e)})).then((()=>e())),()=>this.listeners.get(s)?.delete(e)),dispose:async()=>{o.count--,o.count<=0&&(this.watcherCache.delete(s),"transient"===n.scope&&await this.unregister(s),a=!0,this.notifyListeners(s),this.listeners.delete(s))}};return this.watcherCache.set(s,o),o}peek(e){return this.artifacts.get(e)?.instance??this.parent?.peek(e)}findDefinition(e){return this.artifacts.has(e)?{def:this.artifacts.get(e),container:this}:this.parent?this.parent.findDefinition(e):null}packageArtifact(e){const t=this.resolvedArtifacts.get(e.key),r=(t,r=!1)=>(t.instance=e.instance,t.cleanup=this.createCompositeCleanup(e.cleanupFunctions),t.error=e.error,t.ready=void 0===e.initializationPromise,t.invalidate=async t=>this.invalidate(e.key,t),r&&this.resolvedArtifacts.set(e.key,t),t);return t?r(t):r({},"singleton"===e.scope)}async createArtifactInstance(e,t,r){e.buildCount++;const n=[],i=[];let s=!0;e.activeDebounceMs=e.baseDebounceMs,n.push((()=>{s=!1}));const a={state:(...e)=>this.props.get(...e),current:e.instance,onCleanup:e=>n.push(e),onDispose:e=>i.push(e),use:async(n,i)=>(i?.debounce&&i.debounce>e.activeDebounceMs&&(e.activeDebounceMs=i.debounce),n({resolve:async r=>{if(r===e.key)throw new l(`Artifact "${String(e.key)}" depends on itself.`,"system");const n=this.findDefinition(r);return n&&(t.add({key:r,container:n.container}),n.container.registerDependent(r,e.key,this)),this.resolve(r)},select:e=>(function(e,t="."){const r=new Set,n=(e=[])=>new Proxy({},{get:(i,s)=>{if("symbol"==typeof s)return;const a=[...e,s],o=a.join(t);return r.add(o),n(a)}});try{e(n())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}const i=Array.from(r);return i.filter((e=>!i.some((r=>r!==e&&r.startsWith(e+t)))))}(e).forEach((e=>r.add(e))),e(this.props.get()))})),yield:t=>{queueMicrotask((()=>{s&&("transient"!==e.scope?(e.instance=t,e.error=void 0,this.processYieldPropagation(e.key)):console.error(`[ArtifactContainer] Illegal yield on transient artifact "${String(e.key)}"`))}))}};let o,c,d=0;const p=(e.retries||0)+1;for(;d<p;)try{const t=e.factory(a);if(e.timeoutMs){const r=new Promise(((t,r)=>setTimeout((()=>r(new Error(`Timeout: ${e.timeoutMs}ms`))),e.timeoutMs)));o=await Promise.race([t,r])}else o=await t;break}catch(e){if(e instanceof l)throw e;d++,d>=p&&(c=e)}return"singleton"===e.scope&&(e.cleanupFunctions=n,e.disposeFunctions=i),{instance:o,cleanup:this.createCompositeCleanup(n),error:c}}async processYieldPropagation(e){const t=this.artifacts.get(e);if(t)try{await Promise.all(Array.from(t.dependents).map((e=>e.container.invalidate(e.key,!1).catch((t=>{console.error(`[ArtifactContainer] Failed to invalidate dependent "${e.key}":`,t)}))))),this.notifyListeners(e)}catch(t){console.error(`[ArtifactContainer] Yield propagation error "${e}":`,t)}}registerDependent(e,t,r){const n=this.artifacts.get(e);n&&n.dependents.add({key:t,container:r})}removeDependent(e,t,r){const n=this.artifacts.get(e);if(n)for(const e of n.dependents)if(e.key===t&&e.container===r){n.dependents.delete(e);break}}async invalidate(e,t=!1){const r=e,n=this.artifacts.get(r);if(n){if(n.debounceTimer&&(clearTimeout(n.debounceTimer),n.debounceTimer=void 0,n.isInvalidationScheduled=!1),!t&&n.activeDebounceMs>0&&!n.isInvalidationScheduled){n.isInvalidationScheduled=!0;const r=new Promise((r=>{n.debounceTimer=setTimeout((()=>{n.debounceTimer=void 0,n.isInvalidationScheduled=!1,this.executeInvalidation(e,t).then(r).catch(r)}),n.activeDebounceMs)}));return n.rebuildPromise=r,r}return t&&n.isInvalidationScheduled&&(n.isInvalidationScheduled=!1),this.executeInvalidation(e,t)}}async executeInvalidation(e,t){const r=e,n=this.artifacts.get(r);if(!n)return;if(n.initializationPromise)try{await n.initializationPromise}catch{}if(n.rebuildPromise&&!n.debounceTimer&&!t)return n.rebuildPromise;const i=(async()=>{try{await Promise.all(Array.from(n.dependents).map((e=>e.container.invalidate(e.key,t).catch((t=>{console.error(`[ArtifactContainer] Cascade failed for "${e.key}":`,t)}))))),await this.disposeInstance(n,!1),(t||!n.lazy||this.watcherCache.has(r))&&(await this.resolve(e),this.notifyListeners(r))}finally{n.rebuildPromise=void 0}})();return n.rebuildPromise=i,i}async disposeInstance(e,t=!0){e.stateSubscriptionCleanup&&(e.stateSubscriptionCleanup(),e.stateSubscriptionCleanup=void 0),e.debounceTimer&&(clearTimeout(e.debounceTimer),e.debounceTimer=void 0);for(let t=e.disposeFunctions.length-1;t>=0;t--)try{await e.disposeFunctions[t]()}catch(e){console.error(e)}for(let t=e.cleanupFunctions.length-1;t>=0;t--)try{await e.cleanupFunctions[t]()}catch(e){console.error(e)}e.instance=void 0,e.error=void 0,e.cleanupFunctions=[],e.disposeFunctions=[],e.initializationPromise=void 0,this.resolvedArtifacts.get(e.key)&&this.resolvedArtifacts.delete(e.key),t&&this.notifyListeners(e.key)}async disposeArtifact(e){const t=this.artifacts.get(e);t&&(this.watcherCache.delete(e),t.rebuildPromise&&await t.rebuildPromise,await this.disposeInstance(t),t.artifactDependencies.forEach((t=>{t.container.removeDependent(t.key,e,this)})))}updateGraph(e,t,r){e.artifactDependencies.forEach((r=>{let n=!1;for(const e of t)if(e.key===r.key&&e.container===r.container){n=!0;break}n||r.container.removeDependent(r.key,e.key,this)})),t.forEach((t=>{t.container.registerDependent(t.key,e.key,this)})),e.artifactDependencies=t,e.stateSubscriptionCleanup&&e.stateSubscriptionCleanup(),e.stateDependencies=r,r.size>0?e.stateSubscriptionCleanup=this.props.watch(Array.from(r),(()=>this.invalidate(e.key,!1))):e.stateSubscriptionCleanup=void 0,this.notifyListeners(e.key)}createCompositeCleanup(e){if(e.length)return async()=>{for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(e)}}}notifyListeners(e){const t=this.listeners.get(e);t&&t.forEach((t=>{try{t()}catch(t){console.error(`[ArtifactContainer] Listener error for "${e}":`,t)}}))}dispose(){this.isDisposed=!0,this.artifacts.forEach(((e,t)=>this.disposeArtifact(t))),this.artifacts.clear(),this.watcherCache.clear(),this.listeners.clear()}},exports.ArtifactError=l,exports.ArtifactNotFoundError=p,exports.ArtifactScopes=h,exports.CircularDependencyError=d,exports.IllegalScopeError=class extends l{constructor(e){super(`[ArtifactContainer] ${e}`,"system")}},exports.WatcherDisposedError=u;
|
|
1
|
+
"use strict";var e,t,r=Object.create,s=Object.defineProperty,n=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,c=(e={"src/store/node_modules/@asaidimu/events/index.js"(e,t){var r,s=Object.defineProperty,n=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o={};((e,t)=>{for(var r in t)s(e,r,{get:t[r],enumerable:!0})})(o,{createEventBus:()=>c}),t.exports=(r=o,((e,t,r,o)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of i(t))a.call(e,c)||c===r||s(e,c,{get:()=>t[c],enumerable:!(o=n(t,c))||o.enumerable});return e})(s({},"__esModule",{value:!0}),r));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let r=[],s=0,n=0;const i=new Map,a=new Map;let o=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?o=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{s++,n+=t,i.set(e,(i.get(e)||0)+1)},h=()=>{const t=r;r=[],t.forEach((({name:t,payload:r})=>{const s=performance.now();try{(a.get(t)||[]).forEach((e=>e(r)))}catch(s){e.errorHandler({...s,eventName:t,payload:r})}c(t,performance.now()-s)}))},d=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(h,e.batchDelay)}})(),l=e=>{const r=t.get(e);r?a.set(e,Array.from(r)):a.delete(e)};return o&&(o.onmessage=e=>{const{name:t,payload:r}=e.data;(a.get(t)||[]).forEach((e=>e(r)))}),{subscribe:(e,r)=>{t.has(e)||t.set(e,new Set);const s=t.get(e);return s.add(r),l(e),()=>{s.delete(r),0===s.size?(t.delete(e),a.delete(e)):l(e)}},emit:({name:t,payload:s})=>{if(e.async)return r.push({name:t,payload:s}),r.length>=e.batchSize?h():d(),void(o&&o.postMessage({name:t,payload:s}));const n=performance.now();try{(a.get(t)||[]).forEach((e=>e(s))),o&&o.postMessage({name:t,payload:s})}catch(r){e.errorHandler({...r,eventName:t,payload:s})}c(t,performance.now()-n)},getMetrics:()=>({totalEvents:s,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:i,averageEmitDuration:s>0?n/s:0}),clear:()=>{t.clear(),a.clear(),r=[],s=0,n=0,i.clear(),o&&(o.close(),o=null)}}}}},function(){return t||(0,e[i(e)[0]])((t={exports:{}}).exports,t),t.exports}),h=(e=>(e.Singleton="singleton",e.Transient="transient",e))(h||{}),d=class e extends Error{category;constructor(t,r,s){super(t,{cause:s}),this.name="ArtifactError",this.category=r,Object.setPrototypeOf(this,e.prototype)}},l=class extends d{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system")}},u=class extends d{constructor(e){super(`[ArtifactContainer] Artifact with key:${e} has already been disposed`,"system")}},p=class extends d{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`,"system")}},g=class extends d{constructor(e){super(`[ArtifactContainer] An artifact with key:${e} already exists!`,"system")}},f=class extends d{constructor(){super("[Serializer] The serializer has been marked as done!","system")}},y=class{artifacts=new Map;register({key:e,factory:t,lazy:r,...s}){if(this.artifacts.has(e))throw new g(String(e));const{scope:n,...i}=s,a={key:e,factory:t,scope:s.scope??"singleton",lazy:void 0===r||r,...i};return this.artifacts.set(e,a),()=>this.unregister(e)}get(e){if(!this.has(e))throw new l(String(e));return this.artifacts.get(e)}has(e){return this.artifacts.has(e)}async unregister(e){this.artifacts.has(e)&&this.artifacts.delete(e)}size(){return this.artifacts.size}keys(){return Array.from(this.artifacts.keys())}clear(){this.artifacts.clear()}};((e,t,c)=>{c=null!=e?r(a(e)):{},((e,t,r,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of i(t))o.call(e,c)||c===r||s(e,c,{get:()=>t[c],enumerable:!(a=n(t,c))||a.enumerable})})(e&&e.__esModule?c:s(c,"default",{value:e,enumerable:!0}),e)})(c());var m=class{_locked=!1;_capacity;waiters=[];constructor(e){this._capacity=e?.capacity??1/0}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const r=new Promise((e=>t=e));if(this.waiters.push(t),null!=e)try{await Promise.race([r,new Promise(((r,s)=>setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),s(new p("Mutex lock timed out"))}),e)))])}catch(e){throw e}else await r}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},w=class{constructor(e=!1,t=!1){this.retry=e,this.throws=t}mutex=new m;promise=null;_value=null;_error;_done=!1;async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{const t=await e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(this.promise=null)}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}running(){return null!==this.promise&&!this._done}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){this._done=!1,this.promise=null,this._value=null,this._error=void 0}resolved(){return this.promise}done(){return this._done}_awaitWithTimeout(e,t,r="Operation timed out"){return null==t?e:Promise.race([e,new Promise(((e,s)=>setTimeout((()=>s(new p(r))),t)))])}},v=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;constructor(e){this.mutex=new m({capacity:e?.capacity??1e3})}async do(e,t){if(this._done)return{value:null,error:new f};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let r,s=null;try{if(this._done)throw new f;s=await e(),this._lastValue=s,this._lastError=void 0}catch(e){r=e,this._lastError=e}finally{this.mutex.unlock()}return{value:s,error:r}}peek(){return{value:this._lastValue,error:this._lastError}}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},b=class{constructor(e,t,r,s,n){this.registry=e,this.cache=t,this.graph=r,this.store=s,this.observer=n}async build(e,t){const r=this.registry.get(e);if(!r)throw new d(`Template not found for artifact "${String(e)}"`,"system");const s=t?new Set(t):new Set;if(s.has(e))throw new d(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${Array.from(s).join(" -> ")}`,"system");s.add(e);let n=this.cache.get(e);n||(n=this.createCachedArtifact(r),this.cache.set(e,n));const i=await("transient"===r.scope?this.executeBuild(r,n,s):n.buildOnce.do((()=>this.executeBuild(r,n,s))));if("transient"===r.scope)return i;const a=this.cache.package(e,(t=>this.invalidate(e,t)));return n.stream&&n.streamOnce.do(n.stream),a}async executeBuild(e,t,r){const s=e.key;t.buildCount++;const n=[],i=[];let a=!0;t.activeDebounceMs=e.debounce??0,n.push((()=>{a=!1}));const o=new Set,c=new Set,h=new Map,l={state:()=>this.store.get(!0),current:t.instance,onCleanup:e=>n.push(e),onDispose:e=>i.push(e),use:async e=>e({resolve:async e=>{if(e===s)throw new d(`Artifact "${String(s)}" depends on itself.`,"system");const t=this.graph.wouldCreateCycle(s,e,r);if(t)throw new d(`Adding dependency "${String(e)}" to "${String(s)}" would create a cycle: ${t.join(" -> ")}`,"system");c.add(e);const n=await this.build(e,r),i=this.cache.get(e);return i&&h.set(e,i.version),n},select:e=>(function(e,t="."){const r=new Set,s=(e=[])=>new Proxy({},{get:(n,i)=>{if("symbol"==typeof i)return;const a=[...e,i],o=a.join(t);return r.add(o),s(a)}});try{e(s())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}const n=Array.from(r);return n.filter((e=>!n.some((r=>r!==e&&r.startsWith(e+t)))))}(e).forEach((e=>o.add(e))),e(this.store.get(!0)))}),stream:async r=>{if("transient"===e.scope)throw new d(`[ArtifactManager] Illegal stream on transient artifact "${String(s)}"`,"system");const n=async(e,r=void 0)=>{await t.streamSerializer.do((async()=>{a&&(t.instance=e,t.error=r,t.version++,this.cache.invalidatePackage(s),await this.processStream(s))}))},i={value:t.instance,signal:t.streamController.signal,emit:e=>n(e)};t.stream=async()=>{try{await r(i)}catch(e){await n(void 0,e),this.invalidate(s,!1,!0)}}}};let u,p,g=0;const f=(e.retries??0)+1;for(;g<f;)try{const t=e.factory(l);if(e.timeout){const r=new Promise(((t,r)=>setTimeout((()=>r(new Error(`Timeout: ${e.timeout}ms`))),e.timeout)));u=await Promise.race([t,r])}else u=await t;break}catch(e){if(e instanceof d)throw e;g++,g>=f&&(p=e)}if(a){for(const[e,t]of h){const r=this.cache.get(e);r&&r.version!==t&&(p=new d(`Build stale on arrival: Dependency "${String(e)}" changed during build.`,"system"))}if("singleton"===e.scope&&this.updateDependencyGraph(s,c,o),"singleton"===e.scope&&(t.cleanupFunctions=n,t.disposeFunctions=i),p?t.error=p:t.instance=u,t.version++,this.cache.invalidatePackage(s),"transient"===e.scope)return{instance:u,cleanup:this.createCompositeCleanup(n),error:p,ready:!0,invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${String(s)}"`)}}else{const e=this.createCompositeCleanup(n);e&&await e()}}async invalidate(e,t=!1,r=!1){const s=this.cache.get(e);if(s)return s.debounceTimer&&(clearTimeout(s.debounceTimer),s.debounceTimer=void 0),!t&&s.activeDebounceMs>0?new Promise((n=>{s.debounceTimer=setTimeout((()=>{s.debounceTimer=void 0,this.executeInvalidation(e,t,r).then(n).catch(n)}),s.activeDebounceMs)})):this.executeInvalidation(e,t,r)}async executeInvalidation(e,t,r=!1){const s=this.cache.get(e);s&&(await s.invalidationOnce.do((async()=>{s.version++;const n=this.graph.getDependents(e);await Promise.all(n.map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Cascade failed for "${String(e)}":`,t)}))))),await this.cache.invalidateInstance(e);const i=this.registry.get(e);!i||!t&&i.lazy&&!this.hasWatchers(e)||r||await this.build(e),this.observer.notify(e)})),s.invalidationOnce.reset())}async dispose(e){const t=this.cache.get(e);t&&(t.streamController.abort(),t.buildOnce.running()&&await t.buildOnce.resolved(),t.invalidationOnce.running()&&await t.invalidationOnce.resolved(),t.streamOnce.running()&&await t.streamOnce.resolved(),await this.cache.invalidateInstance(e),this.graph.removeNode(e),this.cache.delete(e))}async processStream(e){try{const t=this.graph.getDependents(e);await Promise.all(t.map((e=>this.invalidate(e).catch((t=>{console.error(`[ArtifactManager] Failed to invalidate dependent "${String(e)}":`,t)}))))),this.observer.notify(e)}catch(t){console.error(`[ArtifactManager] Stream propagation error "${e}":`,t)}}updateDependencyGraph(e,t,r){const s=this.cache.get(e);s&&(this.graph.hasNode(e)||this.graph.registerNode(e),this.graph.setDependencies(e,t),s.stateUnsubscribe&&s.stateUnsubscribe(),s.stateDependencies=r,r.size>0&&(s.stateUnsubscribe=this.store.watch(Array.from(r),(async()=>{await this.invalidate(e)}))))}createCachedArtifact(e){return{instance:void 0,version:0,streamController:new AbortController,error:void 0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,buildOnce:new w(!0,!0),streamOnce:new w(!0,!0),streamSerializer:new v,activeDebounceMs:e.debounce??0,invalidationOnce:new w(!0,!1)}}createCompositeCleanup(e){if(e.length)return async()=>{for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error("[ArtifactManager] Cleanup error:",e)}}}hasWatchers(e){return this.observer.hasWatchers(e)??!1}},C=class{dependencies=new Map;dependents=new Map;metadata=new Map;registerNode(e,t){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set),void 0!==t&&this.metadata.set(e,t)}removeNode(e){if(!this.hasNode(e))return;const t=this.dependencies.get(e);if(t)for(const r of t)this.dependents.get(r)?.delete(e);const r=this.dependents.get(e);if(r)for(const t of r)this.dependencies.get(t)?.delete(e);this.dependencies.delete(e),this.dependents.delete(e),this.metadata.delete(e)}hasNode(e){return this.dependencies.has(e)}addDependency(e,t){this.registerNode(e),this.registerNode(t),this.dependencies.get(e).add(t),this.dependents.get(t).add(e)}removeDependency(e,t){this.dependencies.get(e)?.delete(t),this.dependents.get(t)?.delete(e)}getDependencies(e){const t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){const t=this.dependents.get(e);return t?new Set(t):new Set}getMetadata(e){return this.metadata.get(e)}setMetadata(e,t){this.registerNode(e),this.metadata.set(e,t)}setDependencies(e,t){this.registerNode(e);const r=this.dependencies.get(e),s=new Set(t);for(const t of r)s.has(t)||this.removeDependency(e,t);for(const t of s)r.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const r=[t],s=new Set([t]),n=new Map;for(;r.length>0;){const i=r.shift();if(i===e){const r=[];let s=e;for(;void 0!==s&&(r.push(s),s!==t);)s=n.get(s);return r.reverse(),[e,...r]}const a=this.dependencies.get(i);if(a)for(const e of a)s.has(e)||(s.add(e),n.set(e,i),r.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const r of t)e.set(r,this.dependencies.get(r)?.size??0);const r=[];for(const[t,s]of e)0===s&&r.push(t);const s=[];for(;r.length>0;){const t=r.shift();s.push(t);const n=this.dependents.get(t);if(n)for(const t of n){const s=(e.get(t)||0)-1;e.set(t,s),0===s&&r.push(t)}}if(s.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return s}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,r){const s=new Set,n=new Set,i=[e];n.add(e),r&&s.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;i.length>0;){const e=i.shift(),t=a.get(e);if(t)for(const e of t)n.has(e)||(n.add(e),s.add(e),i.push(e))}return s}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear(),this.metadata.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const r=Array.from(t).join(", ");return`${String(e)} → [${r||"∅"}]`})).join("\n")}},A=class{graph;constructor(){this.graph=new C}registerNode(e){this.graph.registerNode(e)}removeNode(e){this.graph.removeNode(e)}addDependency(e,t){this.graph.addDependency(e,t)}removeDependency(e,t){this.graph.removeDependency(e,t)}getDependents(e){const t=this.graph.getDependents(e);return Array.from(t)}getDependencies(e){const t=this.graph.getDependencies(e);return Array.from(t)}getTransitiveDependents(e){const t=this.graph.getTransitiveDependents(e,!1);return new Set(Array.from(t))}setDependencies(e,t){const r=Array.from(t).map((e=>e));this.graph.setDependencies(e,r)}wouldCreateCycle(e,t,r){if(r?.has(t)){const e=Array.from(r),s=e.indexOf(t),n=e.slice(s);return n.push(t),n}const s=this.graph.wouldCreateCycle(e,t);return s||null}hasNode(e){return this.graph.hasNode(e)}getAllNodes(){return this.graph.getAllNodes()}clear(){this.graph.clear()}size(){return this.graph.size()}toDebugString(){return this.graph.toDebugString()}},_=class{cache=new Map;get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t)}delete(e){this.cache.delete(e)}has(e){return this.cache.has(e)}clear(){this.cache.clear()}size(){return this.cache.size}keys(){return Array.from(this.cache.keys())}package(e,t){const r=this.get(e);if(!r)return{instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:t};if(r.packagedArtifact)return this.updatePackagedArtifact(r,r.packagedArtifact,t),r.packagedArtifact;const s={instance:r.instance,error:r.error,ready:r.buildOnce.done()&&!r.buildOnce.running(),cleanup:this.createCompositeCleanup(r.cleanupFunctions),invalidate:t};return r.packagedArtifact=s,s}async invalidatePackage(e){const t=this.get(e);t&&(t.packagedArtifact=void 0)}async invalidateInstance(e){const t=this.get(e);if(t){t.stateUnsubscribe&&(t.stateUnsubscribe(),t.stateUnsubscribe=void 0),t.debounceTimer&&(clearTimeout(t.debounceTimer),t.debounceTimer=void 0),t.streamController.abort(),await t.streamOnce.resolved(),t.streamOnce.reset(),t.streamSerializer.close();for(let e=t.disposeFunctions.length-1;e>=0;e--)try{await t.disposeFunctions[e]()}catch(e){console.error("[ArtifactManager] Dispose error:",e)}for(let e=t.cleanupFunctions.length-1;e>=0;e--)try{await t.cleanupFunctions[e]()}catch(e){console.error("[ArtifactManager] Cleanup error:",e)}t.instance=void 0,t.error=void 0,t.cleanupFunctions=[],t.disposeFunctions=[],t.buildOnce.reset(),t.stream=void 0,t.streamSerializer=new v,t.streamController=new AbortController}}updatePackagedArtifact(e,t,r){t.instance=e.instance,t.error=e.error,t.ready=e.buildOnce.done()&&!e.buildOnce.running(),t.cleanup=this.createCompositeCleanup(e.cleanupFunctions),t.invalidate=r}createCompositeCleanup(e){if(e.length)return async()=>{for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error("[ArtifactCache] Cleanup error:",e)}}}},k=class{constructor(e,t,r){this.registry=e,this.cache=t,this.container=r}listeners=new Map;watcherCache=new Map;watch(e){const t=e,r=this.registry.get(e);if(!r)throw new Error(`Artifact "${t}" not registered`);let s=t;if("transient"===r.scope&&(s=`${t}__watched`,this.registry.has(s)||this.registry.register({key:s,factory:r.factory,scope:"singleton",lazy:r.lazy,timeout:r.timeout,retries:r.retries,debounce:r.debounce})),this.watcherCache.has(s)){const e=this.watcherCache.get(s);return e.count++,e}let n=!1;const i={id:t,count:1,get:()=>{if(!this.cache.get(s))return this.cache.package(s,(e=>this.container.invalidate(s,e)));const e=this.cache.package(s,(e=>this.container.invalidate(s,e)));return n?{...e,ready:!1,instance:void 0,error:new u(t),cleanup:()=>{},invalidate:()=>Promise.resolve()}:e},subscribe:e=>{this.listeners.has(s)||this.listeners.set(s,new Set);const t=()=>e(i.get());return this.listeners.get(s).add(t),this.container.resolve(s).catch((e=>{console.error(`[ArtifactObserver] Background resolution failed for "${s}":`,e)})).then(t),()=>this.listeners.get(s)?.delete(t)},dispose:async()=>{i.count--,i.count<=0&&(this.watcherCache.delete(s),"transient"===r.scope&&(await this.registry.unregister(s),this.cache.delete(s)),n=!0,this.notify(s),this.listeners.delete(s))}};return this.watcherCache.set(s,i),i}notify(e){const t=this.listeners.get(e);t&&t.forEach((t=>{try{t()}catch(t){console.error(`[ArtifactObserver] Listener error for "${e}":`,t)}}))}hasWatchers(e){return this.watcherCache.has(e)||this.watcherCache.has(`${e}__watched`)}getWatcherCount(e){const t=this.watcherCache.get(e)||this.watcherCache.get(`${e}__watched`);return t?.count??0}clear(){this.watcherCache.clear(),this.listeners.clear()}};exports.ArtifactContainer=class{registry;cache;graph;manager;observer;store;constructor(e){this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0)},this.registry=new y,this.cache=new _,this.graph=new A,this.observer=new k(this.registry,this.cache,this),this.manager=new b(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const r=this.registry.get(t),s=this.cache.get(t);if(!r)return;const n=s?s.buildOnce.running()?"pending":s.error?"error":void 0!==s.instance?"active":"idle":"idle";e.push({id:t,scope:r.scope??"singleton",status:n,dependencies:this.graph.getDependencies(t).map((e=>String(e))),dependents:this.graph.getDependents(t).map((e=>String(e))),stateDependencies:s?Array.from(s.stateDependencies):[],renderCount:s?.buildCount??0})})),e}register(e){const{key:t}=e,r=t;this.registry.has(t)&&(console.warn(`[ArtifactContainer] Overwriting "${r}".`),this.manager.dispose(t).catch((e=>{console.error(`[ArtifactContainer] Failed to dispose existing artifact "${r}":`,e)}))),this.registry.register(e),this.graph.registerNode(t);const s=e.scope??"singleton";return(e.lazy??!0)||"singleton"!==s||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${r}":`,e)})),()=>this.unregister(t)}async unregister(e){await this.manager.dispose(e),await this.registry.unregister(e)}async resolve(e){if(!this.registry.has(e))throw new l(e);return this.manager.build(e)}watch(e){if(!this.registry.has(e))throw new l(e);return this.observer.watch(e)}peek(e){const t=this.cache.get(e);if(void 0!==t?.instance)return t?.instance}async invalidate(e,t=!1){return this.manager.invalidate(e,t)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}dispose(){this.registry.keys().forEach((e=>{this.manager.dispose(e).catch((t=>{console.error(`[ArtifactContainer] Failed to dispose artifact "${String(e)}":`,t)}))})),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear()}},exports.ArtifactScopes=h;
|