@asaidimu/utils-pipeline 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -276
- package/index.d.mts +163 -38
- package/index.d.ts +163 -38
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -524,6 +524,13 @@ interface DataStore<T extends object> {
|
|
|
524
524
|
* @returns The current state T.
|
|
525
525
|
*/
|
|
526
526
|
get(clone?: boolean): T;
|
|
527
|
+
/**
|
|
528
|
+
* Gets a subset of the store.
|
|
529
|
+
* @param paths The paths which to include in the returned object.
|
|
530
|
+
* @param separator Optional separator for paths. Defaults to `.` .
|
|
531
|
+
* @returns An object of the shape K mapping paths to their current values.
|
|
532
|
+
*/
|
|
533
|
+
subset<K extends Record<string, any> = Record<string, any>>(paths: Array<string>, separator?: string): K;
|
|
527
534
|
/**
|
|
528
535
|
* Registers a named action function that can modify the state.
|
|
529
536
|
* @param action The action configuration object.
|
|
@@ -993,6 +1000,24 @@ interface ArtifactTemplate<TState extends object, TArtifact, TRegistry extends R
|
|
|
993
1000
|
paramKey?: (params: Record<string, unknown>) => string;
|
|
994
1001
|
virtual?: true;
|
|
995
1002
|
}
|
|
1003
|
+
interface ExportedArtifact {
|
|
1004
|
+
key: string;
|
|
1005
|
+
instance: any;
|
|
1006
|
+
state: {
|
|
1007
|
+
groups: Array<{
|
|
1008
|
+
paths: string[];
|
|
1009
|
+
options?: SubscribeOptions;
|
|
1010
|
+
}>;
|
|
1011
|
+
hash: string;
|
|
1012
|
+
};
|
|
1013
|
+
dependencies: string[];
|
|
1014
|
+
}
|
|
1015
|
+
interface ExportedContainerState {
|
|
1016
|
+
version: string;
|
|
1017
|
+
timestamp: number;
|
|
1018
|
+
artifacts: ExportedArtifact[];
|
|
1019
|
+
checksum: string;
|
|
1020
|
+
}
|
|
996
1021
|
|
|
997
1022
|
/**
|
|
998
1023
|
* A dependency injection container for managing the lifecycle, dependencies,
|
|
@@ -1019,7 +1044,7 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
1019
1044
|
* Creates a new ArtifactContainer instance.
|
|
1020
1045
|
* @param store An object providing functions to interact with a global data store
|
|
1021
1046
|
*/
|
|
1022
|
-
constructor(store: Pick<DataStore<TState>, "watch" | "get" | "set">);
|
|
1047
|
+
constructor(store: Pick<DataStore<TState>, "watch" | "get" | "set" | "subset">);
|
|
1023
1048
|
/**
|
|
1024
1049
|
* Provides debug information about all artifacts currently registered in this container.
|
|
1025
1050
|
*
|
|
@@ -1136,6 +1161,13 @@ declare class ArtifactContainer<TRegistry extends Record<string, any> = Record<s
|
|
|
1136
1161
|
* Callers should await this method to guarantee full resource release.
|
|
1137
1162
|
*/
|
|
1138
1163
|
dispose(): Promise<void>;
|
|
1164
|
+
export(): Promise<ExportedContainerState>;
|
|
1165
|
+
private restore;
|
|
1166
|
+
static from<TRegistry extends Record<string, any> = Record<string, any>, TState extends object = any>(options: {
|
|
1167
|
+
store: Pick<DataStore<TState>, "watch" | "get" | "set" | "subset">;
|
|
1168
|
+
bundle?: ExportedContainerState;
|
|
1169
|
+
templates: ArtifactTemplate<TState, any, TRegistry>[];
|
|
1170
|
+
}): Promise<ArtifactContainer<TRegistry, TState>>;
|
|
1139
1171
|
}
|
|
1140
1172
|
|
|
1141
1173
|
/**
|
|
@@ -1150,17 +1182,27 @@ interface State {
|
|
|
1150
1182
|
[key: string]: any;
|
|
1151
1183
|
}
|
|
1152
1184
|
/**
|
|
1153
|
-
* Instructs the
|
|
1154
|
-
*
|
|
1185
|
+
* Instructs the factory to pause the pipeline.
|
|
1186
|
+
*
|
|
1187
|
+
* - `pause` — the `stageId` at which the pipeline should resume.
|
|
1188
|
+
* - `timeout` — how long (ms) the registry should hold the live RunContext
|
|
1189
|
+
* before running the deferred container export and clearing the
|
|
1190
|
+
* strong reference. Omit to use the registry's configured default.
|
|
1191
|
+
* A value of 0 means export immediately on pause (no deferral).
|
|
1192
|
+
* - `persist` — kept for backward compatibility; when true the registry will
|
|
1193
|
+
* always export the container bundle at expiry regardless of
|
|
1194
|
+
* whether resume was called. Ignored if timeout is 0.
|
|
1155
1195
|
*/
|
|
1156
1196
|
interface PauseInstruction {
|
|
1157
1197
|
readonly pause: string;
|
|
1198
|
+
readonly timeout?: number;
|
|
1199
|
+
readonly persist?: boolean;
|
|
1158
1200
|
}
|
|
1159
1201
|
/**
|
|
1160
1202
|
* All possible outcomes of a router:
|
|
1161
|
-
* - `string`
|
|
1162
|
-
* - `null`
|
|
1163
|
-
* - `undefined`
|
|
1203
|
+
* - `string` → jump to a named stage
|
|
1204
|
+
* - `null` → terminate the pipeline
|
|
1205
|
+
* - `undefined` → advance to the next stage in order (or natural end)
|
|
1164
1206
|
* - `PauseInstruction` → suspend and write a checkpoint
|
|
1165
1207
|
*/
|
|
1166
1208
|
type RoutingInstruction = string | null | undefined | PauseInstruction;
|
|
@@ -1183,6 +1225,10 @@ type PipelineStageRouter<S extends object> = (state: S, results: Record<string,
|
|
|
1183
1225
|
*
|
|
1184
1226
|
* The checkpoint is always written atomically with the state patches of the
|
|
1185
1227
|
* stage that triggered the pause.
|
|
1228
|
+
*
|
|
1229
|
+
* `containerBundle` is intentionally absent at write time — the factory never
|
|
1230
|
+
* exports. The registry writes it into the checkpoint (via writeCheckpoint)
|
|
1231
|
+
* when the pause timeout fires and the live RunContext is about to be released.
|
|
1186
1232
|
*/
|
|
1187
1233
|
interface PipelineCheckpoint {
|
|
1188
1234
|
readonly runId: string;
|
|
@@ -1191,8 +1237,10 @@ interface PipelineCheckpoint {
|
|
|
1191
1237
|
readonly pausedAtStageId: string;
|
|
1192
1238
|
readonly pausedAtStageLabel: string;
|
|
1193
1239
|
readonly pausedOn: string;
|
|
1240
|
+
/** Written by the registry at timeout expiry, never by the factory. */
|
|
1241
|
+
readonly containerBundle?: ExportedContainerState;
|
|
1194
1242
|
}
|
|
1195
|
-
/**
|
|
1243
|
+
/** Factory-internal namespace for all checkpoint data. */
|
|
1196
1244
|
declare const PIPELINE_DATA_KEY: "__pipeline_data__";
|
|
1197
1245
|
/**
|
|
1198
1246
|
* Run-scoped context injected into every step action as a second argument.
|
|
@@ -1353,10 +1401,14 @@ type EventPath = readonly PathNode[];
|
|
|
1353
1401
|
/**
|
|
1354
1402
|
* All events emitted during a run.
|
|
1355
1403
|
*
|
|
1356
|
-
* stage:paused (#
|
|
1404
|
+
* stage:paused (#8) is a dedicated event for stages that pause, distinct from
|
|
1357
1405
|
* stage:success. Consumers should listen to both if they want to react to all
|
|
1358
1406
|
* terminal stage outcomes. stage:success is only emitted when the stage
|
|
1359
1407
|
* advances (or terminates) — never when it pauses.
|
|
1408
|
+
*
|
|
1409
|
+
* pipeline:paused carries `pauseTimeout` forwarded from the PauseInstruction
|
|
1410
|
+
* so the PipelineRegistry can arm its cleanup timer with the correct duration
|
|
1411
|
+
* without re-reading or re-parsing the instruction.
|
|
1360
1412
|
*/
|
|
1361
1413
|
interface RunEventMap<S extends object> {
|
|
1362
1414
|
"pipeline:start": {
|
|
@@ -1379,6 +1431,12 @@ interface RunEventMap<S extends object> {
|
|
|
1379
1431
|
runId: string;
|
|
1380
1432
|
checkpoint: PipelineCheckpoint;
|
|
1381
1433
|
finalState: S;
|
|
1434
|
+
/**
|
|
1435
|
+
* The timeout value from the PauseInstruction, forwarded verbatim.
|
|
1436
|
+
* Undefined means the registry should use its configured default.
|
|
1437
|
+
* 0 means export immediately (no deferral window).
|
|
1438
|
+
*/
|
|
1439
|
+
pauseTimeout: number | undefined;
|
|
1382
1440
|
};
|
|
1383
1441
|
"pipeline:failure": {
|
|
1384
1442
|
path: EventPath;
|
|
@@ -1465,8 +1523,8 @@ interface ScopedEventBus<S extends object> {
|
|
|
1465
1523
|
on<K extends keyof RunEventMap<S>>(event: K, handler: RunEventHandler<S, K>): () => void;
|
|
1466
1524
|
}
|
|
1467
1525
|
/**
|
|
1468
|
-
* A unit of execution returned by {@link
|
|
1469
|
-
* {@link
|
|
1526
|
+
* A unit of execution returned by {@link PipelineFactory.prepare} or
|
|
1527
|
+
* {@link PipelineFactory.resume}.
|
|
1470
1528
|
*
|
|
1471
1529
|
* Subscribe to lifecycle events via {@link on}, abort via {@link abort}, and
|
|
1472
1530
|
* start execution with {@link run}.
|
|
@@ -1491,27 +1549,29 @@ interface RunContext<S extends object> {
|
|
|
1491
1549
|
*/
|
|
1492
1550
|
run(): Promise<Result<PipelineRunResult<S>>>;
|
|
1493
1551
|
}
|
|
1494
|
-
/** Minimal logger interface used by the
|
|
1552
|
+
/** Minimal logger interface used by the factory. */
|
|
1495
1553
|
interface EngineLogger {
|
|
1496
1554
|
info: (msg: string, ctx?: any) => void;
|
|
1497
1555
|
error: (msg: string, ctx?: any) => void;
|
|
1498
1556
|
}
|
|
1499
1557
|
/**
|
|
1500
|
-
* Configuration for {@link
|
|
1558
|
+
* Configuration for {@link PipelineFactory}.
|
|
1501
1559
|
*
|
|
1502
1560
|
* @typeParam S - The shape of the state managed by the pipeline.
|
|
1503
1561
|
*/
|
|
1504
|
-
interface
|
|
1562
|
+
interface PipelineFactoryOptions<S extends object = State> {
|
|
1505
1563
|
/** Logger (defaults to a no‑op). */
|
|
1506
1564
|
logger?: EngineLogger;
|
|
1507
1565
|
/**
|
|
1508
1566
|
* **Required.** A factory that, given a `runId`, returns a `DataStore<S>`.
|
|
1509
|
-
* The
|
|
1510
|
-
* isolated store instance.
|
|
1567
|
+
* The factory does **not** hold a global store; each run receives its own
|
|
1568
|
+
* isolated store instance from this function.
|
|
1511
1569
|
*
|
|
1512
|
-
* For a new run (`prepare`), the
|
|
1570
|
+
* For a new run (`prepare`), the function should return an empty store.
|
|
1513
1571
|
* For a resumed run (`resume`), it must return the **same** store that was
|
|
1514
1572
|
* used during the original run (so that state and checkpoints are preserved).
|
|
1573
|
+
*
|
|
1574
|
+
* The returned store is owned by the run, not by PipelineFactory.
|
|
1515
1575
|
*/
|
|
1516
1576
|
storeFactory: (runId: string) => Promise<DataStore<S>>;
|
|
1517
1577
|
/**
|
|
@@ -1520,37 +1580,65 @@ interface PipelineEngineOptions<S extends object = State> {
|
|
|
1520
1580
|
* If omitted, the store remains empty.
|
|
1521
1581
|
*/
|
|
1522
1582
|
initialStateFactory?: () => S;
|
|
1583
|
+
/**
|
|
1584
|
+
* Optional registry to register every RunContext with after construction.
|
|
1585
|
+
* When provided, prepare() and resume() call registry.register() before
|
|
1586
|
+
* returning, passing both the RunContext and the run's DataStore so the
|
|
1587
|
+
* registry can drive deferred export without needing a reference to the factory.
|
|
1588
|
+
*/
|
|
1589
|
+
registry?: PipelineRegistryBinding<S>;
|
|
1590
|
+
}
|
|
1591
|
+
/**
|
|
1592
|
+
* Narrow interface the factory uses to register runs with the registry.
|
|
1593
|
+
* Typed as an interface rather than the full PipelineRegistry class so that
|
|
1594
|
+
* the factory remains decoupled from the registry's full surface.
|
|
1595
|
+
*/
|
|
1596
|
+
interface PipelineRegistryBinding<S extends object> {
|
|
1597
|
+
register(context: RunContext<S>, store: DataStore<S>): void;
|
|
1598
|
+
/**
|
|
1599
|
+
* Called by resume() before constructing a new RunContext.
|
|
1600
|
+
* Returns the existing live RunContext if the registry still holds a strong
|
|
1601
|
+
* reference for this runId (i.e. the pause timeout has not yet fired).
|
|
1602
|
+
* Returns null if no live context exists and reconstruction is needed.
|
|
1603
|
+
*/
|
|
1604
|
+
getLiveContext(runId: string): RunContext<S> | null;
|
|
1523
1605
|
}
|
|
1524
1606
|
/**
|
|
1525
|
-
*
|
|
1607
|
+
* A pure factory for creating and resuming pipeline runs.
|
|
1608
|
+
*
|
|
1609
|
+
* PipelineFactory is stateless between runs. It holds only the pipeline
|
|
1610
|
+
* definition (topology), a storeFactory function, and an optional logger and
|
|
1611
|
+
* registry binding. It does not own any DataStore, timer, or live run state.
|
|
1526
1612
|
*
|
|
1527
1613
|
* @typeParam S - The shape of the state object.
|
|
1528
1614
|
*
|
|
1529
1615
|
* @example
|
|
1530
1616
|
* ```ts
|
|
1531
|
-
* const
|
|
1617
|
+
* const factory = new PipelineFactory(myDefinition, {
|
|
1532
1618
|
* storeFactory: (runId) => createMyStore(runId),
|
|
1533
1619
|
* initialStateFactory: () => ({ counter: 0 }),
|
|
1620
|
+
* registry: PipelineRegistry.default,
|
|
1534
1621
|
* });
|
|
1535
1622
|
*
|
|
1536
|
-
* const ctx = await
|
|
1623
|
+
* const ctx = await factory.prepare({ stage: "validate" });
|
|
1537
1624
|
* ctx.on("pipeline:success", (e) => console.log("done", e.finalState));
|
|
1538
1625
|
* const result = await ctx.run();
|
|
1539
1626
|
* ```
|
|
1540
1627
|
*/
|
|
1541
|
-
declare class
|
|
1628
|
+
declare class PipelineFactory<S extends object> {
|
|
1542
1629
|
private readonly definition;
|
|
1543
1630
|
private readonly logger;
|
|
1544
1631
|
private readonly storeFactory;
|
|
1545
1632
|
private readonly initialStateFactory;
|
|
1633
|
+
private readonly registry;
|
|
1546
1634
|
private readonly index;
|
|
1547
1635
|
/**
|
|
1548
|
-
* Constructs
|
|
1636
|
+
* Constructs a factory tied to a fixed pipeline definition.
|
|
1549
1637
|
*
|
|
1550
1638
|
* @param definition - The pipeline topology (stages, steps, routers).
|
|
1551
|
-
* @param options -
|
|
1639
|
+
* @param options - Factory configuration. `storeFactory` is mandatory.
|
|
1552
1640
|
*/
|
|
1553
|
-
constructor(definition: RoutingPipelineDefinition<S>, options:
|
|
1641
|
+
constructor(definition: RoutingPipelineDefinition<S>, options: PipelineFactoryOptions<S>);
|
|
1554
1642
|
/**
|
|
1555
1643
|
* Prepare an isolated {@link RunContext} for a **new** run.
|
|
1556
1644
|
*
|
|
@@ -1558,6 +1646,9 @@ declare class PipelineEngine<S extends object> {
|
|
|
1558
1646
|
* initial state from `initialStateFactory`. No execution occurs until
|
|
1559
1647
|
* `runContext.run()` is called.
|
|
1560
1648
|
*
|
|
1649
|
+
* If a registry is configured, the context and store are registered before
|
|
1650
|
+
* this method returns.
|
|
1651
|
+
*
|
|
1561
1652
|
* @param entry - Optional address describing where to start execution.
|
|
1562
1653
|
* Omit to start from the lowest‑order stage.
|
|
1563
1654
|
* @param runId - Optional run identifier (UUID v7). Generated if omitted.
|
|
@@ -1567,9 +1658,18 @@ declare class PipelineEngine<S extends object> {
|
|
|
1567
1658
|
/**
|
|
1568
1659
|
* Reconstruct a {@link RunContext} for a previously paused run.
|
|
1569
1660
|
*
|
|
1570
|
-
*
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1661
|
+
* **Fast path (registry hit):** If a registry is configured and still holds
|
|
1662
|
+
* a live strong reference for `runId` (i.e. the pause timeout has not fired),
|
|
1663
|
+
* the existing RunContext is returned directly. No store read, no
|
|
1664
|
+
* ArtifactContainer.from() — zero serialization cost.
|
|
1665
|
+
*
|
|
1666
|
+
* **Slow path (store reconstruction):** If no live context exists (timeout
|
|
1667
|
+
* expired, process restarted, or no registry), the store is read, the
|
|
1668
|
+
* checkpoint is validated, and a fresh RunContext is built from the
|
|
1669
|
+
* containerBundle (if the registry wrote one at expiry) or from scratch.
|
|
1670
|
+
*
|
|
1671
|
+
* The context is registered with the registry before this method returns
|
|
1672
|
+
* (slow path only — the fast path context is already registered).
|
|
1573
1673
|
*
|
|
1574
1674
|
* @param runId - The identifier of the paused run.
|
|
1575
1675
|
* @returns A result containing the `RunContext`, or a failure if no
|
|
@@ -1581,7 +1681,7 @@ declare class PipelineEngine<S extends object> {
|
|
|
1581
1681
|
*
|
|
1582
1682
|
* This method is package-internal. External callers use prepare() or resume().
|
|
1583
1683
|
* Sub-pipelines access it through the {@link SubPipelineFactory} interface,
|
|
1584
|
-
* which is the only reference RunContextImpl holds to the
|
|
1684
|
+
* which is the only reference RunContextImpl holds to the factory.
|
|
1585
1685
|
*
|
|
1586
1686
|
* A single {@link ArtifactContainer} is created per run at root level and
|
|
1587
1687
|
* shared across all sub-pipelines. Steps are registered under namespaced keys
|
|
@@ -1592,16 +1692,41 @@ declare class PipelineEngine<S extends object> {
|
|
|
1592
1692
|
* threaded into {@link registerSteps} so that every step factory closure
|
|
1593
1693
|
* captures the correct signal at registration time.
|
|
1594
1694
|
*
|
|
1595
|
-
* @param runId
|
|
1596
|
-
* @param pipeline
|
|
1597
|
-
* @param entry
|
|
1598
|
-
* @param store
|
|
1599
|
-
* @param parentBus
|
|
1600
|
-
* @param parentPath
|
|
1601
|
-
* @param container
|
|
1602
|
-
* @param keyPrefix
|
|
1603
|
-
|
|
1604
|
-
|
|
1695
|
+
* @param runId - The run identifier (same for parent and sub‑pipelines).
|
|
1696
|
+
* @param pipeline - The pipeline (sub‑)definition.
|
|
1697
|
+
* @param entry - Entry address; `undefined` means start from the beginning.
|
|
1698
|
+
* @param store - The shared store instance for this run.
|
|
1699
|
+
* @param parentBus - Parent scoped bus for event bubbling (root runs pass undefined).
|
|
1700
|
+
* @param parentPath - Event path from the root.
|
|
1701
|
+
* @param container - Shared container (created once at root; passed down to sub-pipelines).
|
|
1702
|
+
* @param keyPrefix - Namespacing prefix for artifact keys within the shared container.
|
|
1703
|
+
* @param artifactBundle - Optional exported container state for store-based resume.
|
|
1704
|
+
*/
|
|
1705
|
+
buildRunContext(runId: string, pipeline: RoutingPipelineDefinition<S>, entry: EntryAddress | undefined, store: DataStore<S>, parentBus: ScopedEventBus<S> | undefined, parentPath: EventPath, container?: ArtifactContainer<Record<string, DeepPartial<S>>, S>, keyPrefix?: string, artifactBundle?: ExportedContainerState): Promise<RunContext<S>>;
|
|
1605
1706
|
}
|
|
1707
|
+
/**
|
|
1708
|
+
* Writes a checkpoint into the store using the typed EngineStoreEnvelope.
|
|
1709
|
+
* The write is synchronous from the store's perspective (the transaction
|
|
1710
|
+
* boundary lives in the caller). No `any` cast is required because
|
|
1711
|
+
* EngineStoreEnvelope fully types the factory-internal key namespace.
|
|
1712
|
+
*
|
|
1713
|
+
* Exported so the PipelineRegistry can update an existing checkpoint with a
|
|
1714
|
+
* containerBundle at timeout expiry without duplicating the write logic.
|
|
1715
|
+
*/
|
|
1716
|
+
declare function writeCheckpoint(store: DataStore<any>, checkpoint: PipelineCheckpoint): Promise<void>;
|
|
1717
|
+
/**
|
|
1718
|
+
* Reads a checkpoint from the store using the typed EngineStoreEnvelope.
|
|
1719
|
+
* Returns null if no checkpoint exists for the given pipelineId / runId pair.
|
|
1720
|
+
* Synchronous — the store's get() is a synchronous snapshot read.
|
|
1721
|
+
*/
|
|
1722
|
+
declare function readCheckpoint(store: DataStore<any>, pipelineId: string | undefined, runId: string): PipelineCheckpoint | null;
|
|
1723
|
+
/**
|
|
1724
|
+
* Removes a checkpoint from the store.
|
|
1725
|
+
* Called by the registry when a paused run expires and no resume arrived,
|
|
1726
|
+
* after the containerBundle (if any) has been written into the checkpoint.
|
|
1727
|
+
* Exported so the registry can clear stale checkpoints without reaching into
|
|
1728
|
+
* the factory's internals.
|
|
1729
|
+
*/
|
|
1730
|
+
declare function clearCheckpoint(store: DataStore<any>, pipelineId: string, runId: string): Promise<void>;
|
|
1606
1731
|
|
|
1607
|
-
export { type EngineLogger, type EntryAddress, type EventPath, PIPELINE_DATA_KEY, type PathNode, type PauseInstruction, Pipeline, type PipelineCheckpoint, type PipelineContext, type PipelineDefinition,
|
|
1732
|
+
export { type EngineLogger, type EntryAddress, type EventPath, PIPELINE_DATA_KEY, type PathNode, type PauseInstruction, Pipeline, type PipelineCheckpoint, type PipelineContext, type PipelineDefinition, type PipelineEventMap, PipelineFactory, type PipelineFactoryOptions, type PipelineRegistryBinding, type PipelineRunResult, type PipelineStageRouter, type PipelineStep, type PipelineStepDefinition, Result, type RoutingInstruction, type RoutingPipelineDefinition, type RunContext, type RunEventHandler, type RunEventMap, SequentialExecutionContext, type Stage, type StageCarry, type State, type Step, type StepStageRouter, type SubPipelineAddress, clearCheckpoint, isPauseInstruction, readCheckpoint, writeCheckpoint };
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("@asaidimu/utils-events"),t=require("uuid"),s={VALIDATION_FAILED:{code:"VAL-001",name:"VALIDATION_FAILED",description:"Input validation failed due to one or more invalid fields",category:"validation",httpStatus:400,logLevel:"warn"},REQUIRED_FIELD_MISSING:{code:"VAL-002",name:"REQUIRED_FIELD_MISSING",description:"A required field was not provided in the request",category:"validation",httpStatus:400,logLevel:"warn"},INVALID_FORMAT:{code:"VAL-003",name:"INVALID_FORMAT",description:"Field value does not match expected format",category:"validation",httpStatus:400,logLevel:"warn"},NOT_FOUND:{code:"DB-001-NF",name:"NOT_FOUND",description:"The requested resource could not be found",category:"database",httpStatus:404,logLevel:"info",action:"Verify the resource identifier exists before accessing"},DUPLICATE_KEY:{code:"DB-002-DUP",name:"DUPLICATE_KEY",description:"A unique constraint violation occurred",category:"database",httpStatus:409,logLevel:"warn",action:"Check if the resource already exists before creation"},RESOURCE_LOCKED:{code:"DB-003-LOCK",name:"RESOURCE_LOCKED",description:"The resource is currently locked by another operation",category:"database",httpStatus:409,logLevel:"warn",action:"Retry the operation after a brief delay"},PERMISSION_DENIED:{code:"AUTH-001-DENIED",name:"PERMISSION_DENIED",description:"The authenticated user lacks permission for this operation",category:"auth",httpStatus:403,logLevel:"warn",action:"Check user roles and permissions"},UNAUTHENTICATED:{code:"AUTH-002-UNAUTH",name:"UNAUTHENTICATED",description:"Authentication is required for this operation",category:"auth",httpStatus:401,logLevel:"info",action:"Provide valid authentication credentials"},INVALID_COMMAND:{code:"BUS-001",name:"INVALID_COMMAND",description:"The command or operation is invalid for the current state",category:"business",httpStatus:400,logLevel:"warn"},OPERATION_ABORTED:{code:"BUS-002-ABORT",name:"OPERATION_ABORTED",description:"The operation was explicitly aborted",category:"business",httpStatus:409,logLevel:"info"},INTERNAL_ERROR:{code:"SYS-001",name:"INTERNAL_ERROR",description:"An unexpected internal error occurred",category:"system",httpStatus:500,logLevel:"error",action:"Check system logs for stack traces and diagnostic information"},BACKEND_ERROR:{code:"SYS-002",name:"BACKEND_ERROR",description:"An error occurred in a backend service",category:"system",httpStatus:502,logLevel:"error"},CONCURRENCY_ERROR:{code:"CON-001",name:"CONCURRENCY_ERROR",description:"A concurrency conflict occurred during the operation",category:"concurrency",httpStatus:409,logLevel:"warn",action:"Retry the operation with updated data"}},i=new Map;var r=class e extends Error{code;codeMetadata;severity;path;operation;issues;cause;constructor(t){const r={...function(e){const t=Object.values(s).find((t=>t.code===e));if(t)return t;return i.get(e)||{code:e,name:e.replace(/-/g,"_"),description:`Unknown error: ${e}`,category:"custom",httpStatus:500,logLevel:"error",action:"Check if this error code is properly registered or handle as unknown error"}}(t.code),...t.metadata,code:t.code};super(t.message??r.description),this.name="SystemError",this.code=t.code,this.codeMetadata=r,this.severity=t.severity??"error",this.path=t.path,this.operation=t.operation,this.issues=t.issues??[],this.cause=t.cause,Object.setPrototypeOf(this,e.prototype),Error.captureStackTrace&&Error.captureStackTrace(this,e)}withPath(t){return new e({code:this.code,message:this.message,severity:this.severity,path:t,operation:this.operation,issues:this.issues,cause:this.cause,metadata:this.codeMetadata})}withOperation(t){return new e({code:this.code,message:this.message,severity:this.severity,path:this.path,operation:t,issues:this.issues,cause:this.cause,metadata:this.codeMetadata})}withIssue(t){return new e({code:this.code,message:this.message,severity:this.severity,path:this.path,operation:this.operation,issues:[...this.issues,t],cause:this.cause,metadata:this.codeMetadata})}withIssues(t){return new e({code:this.code,message:this.message,severity:this.severity,path:this.path,operation:this.operation,issues:[...this.issues,...t],cause:this.cause,metadata:this.codeMetadata})}withCause(t){return new e({code:this.code,message:this.message,severity:this.severity,path:this.path,operation:this.operation,issues:this.issues,cause:t,metadata:this.codeMetadata})}getHttpStatus(){return this.codeMetadata.httpStatus}toLogEntry(){return{name:this.name,code:this.code,category:this.codeMetadata.category,message:this.message,path:this.path,operation:this.operation,issues:this.issues,cause:this.cause instanceof Error?this.cause.message:this.cause,stack:this.stack,timestamp:(new Date).toISOString()}}toString(){let e=`[${this.code}] ${this.message} (${this.codeMetadata.category})`;return this.path&&(e+=` at '${this.path}'`),this.operation&&(e+=` during '${this.operation}'`),this.issues.length>0&&(e+="\nIssues:\n"+this.issues.map(((e,t)=>` ${t+1}. ${e.message} [${e.code}]`)).join("\n")),this.cause&&(e+=`\nCause: ${this.cause instanceof Error?this.cause.message:String(this.cause)}`),e}},n="SYS-001",a=(e,t)=>new r({code:n,message:t,cause:e}),o=e=>({ok:!0,value:e}),c=e=>({ok:!1,error:e}),h=class e extends r{constructor(t,s){super({code:"SYNC_ERROR",message:t,cause:s}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},d=class e extends h{constructor(t){super(`[ArtifactContainer] Operation timed out: ${t}`),this.name="TimeoutError",Object.setPrototypeOf(this,e.prototype)}},u=class e extends h{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)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const s=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await s;let i;await Promise.race([s.then((()=>clearTimeout(i))),new Promise(((s,r)=>{i=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),r(new d("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},p=class{mutex=new l({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(this.promise=null)}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}running(){return null!==this.promise&&!this.done()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,s="Operation timed out"){if(null==t)return e;let i;return Promise.race([e.then((e=>(clearTimeout(i),e))),new Promise(((e,r)=>{i=setTimeout((()=>r(new d(s))),t)}))])}},g=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 u};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let s,i=null;try{if(this._done)throw new u;i=await e(),this._lastValue=i,this._lastError=void 0,this._hasRun=!0}catch(e){s=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:i,error:s}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},f=class{constructor(t,s,i,r,n){this.pipeline=t,this.stepKey=s,this.params=i,r&&(r.aborted&&this.controller.abort(),r.addEventListener("abort",(()=>this.controller.abort()))),this.localBus=n??e.createEventBus()}id=Math.random().toString(36).substring(2,9);localBus;controller=new AbortController;once=new p({retry:!1,throws:!1});get signal(){return this.controller.signal}on(e,t){return this.localBus.subscribe(e,t)}abort(){this.controller.abort()}async run(){const{value:e,error:t}=await this.once.do((()=>this._run()));return t?c(t):e}async _run(){const e=this.pipeline.getSteps().get(this.stepKey);if(!e)return{ok:!1,error:new r({code:s.INVALID_COMMAND.code,message:`No step registered with key "${this.stepKey}"`,operation:this.stepKey})};if(this.signal.aborted)return this.failCancelled("Pipeline execution aborted before initialization",this.stepKey);const t=this.pipeline.groupByOrder(),i=Array.from(t.entries()).sort((([e],[t])=>e-t)),n=e.order;this.emit("start",{stepKey:this.stepKey,executionId:this.id});let a={[this.stepKey]:this.params},o=a,c=!0;for(const[e,t]of i){if(e<n)continue;if(this.signal.aborted)return this.failCancelled(`Pipeline runtime aborted at stage ${e}`,this.stepKey);const s=c?t.filter((e=>e.key===this.stepKey)):t;if(c=!1,0===s.length)continue;const i=await this.runStage(s,a);if(!i.ok)return i;o=i.value,a={...a,...o},this.emit("stage:success",{order:e,executionId:this.id,carry:o})}return this.emit("terminate",{carry:o,executionId:this.id}),{ok:!0,value:o}}async runStage(e,t){const s=await Promise.all(e.map((async e=>{try{if(this.signal.aborted)return{step:e,result:this.failCancelled("Aborted mid-flight execution sequence",e.key)};const s=await e.action(t,this.signal);return{step:e,result:s}}catch(t){return{step:e,result:{ok:!1,error:t instanceof r?t:a(t,t instanceof Error?t.message:"Unexpected exception raised during step run")}}}}))),i={};let n=null;for(const{step:e,result:t}of s)if(t.ok)this.emit("step:success",{stepKey:e.key,executionId:this.id,result:t.value}),i[e.key]=t.value;else{const s=t.error.withOperation(e.key);this.emit("step:failure",{stepKey:e.key,executionId:this.id,error:s}),n||(n={ok:!1,error:s},this.emit("failure",{stepKey:e.key,executionId:this.id,error:s}))}return n||{ok:!0,value:i}}emit(e,t){this.localBus.emit({name:e,payload:t})}failCancelled(e,t){return{ok:!1,error:new r({code:"CANCELLED",message:e,operation:t})}}},y=class{constructor(e,t,s={}){this.factory=e,this.onCleanup=t,this.options=s}_count=0;init=new p({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;const e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){this._count<=0?console.warn("SharedResource.release() called, but count is already 0."):(this._count--,0===this._count&&this.scheduleCleanup())}peek(){const e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,void 0!==this.cleanupTimer&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){const e=this.options.gracePeriod??"microtask";if("sync"!==e)return"microtask"===e?(this.pendingMicrotask=!0,void queueMicrotask((()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())}))):void(this.cleanupTimer=setTimeout((()=>{this.cleanupTimer=void 0,this._count>0||this.executeCleanup()}),e));this.executeCleanup()}executeCleanup(){const e=this.init.peek();try{this.onCleanup(e.value)}catch(e){console.error("[SharedResource] Error during cleanup callback:",e)}this.init.running()||this.init.reset()}};function m(e,t){if(!e.length)return;const s=e.slice(),i=t?`[${t}]`:"[ArtifactCleanup]";return async()=>{for(let e=s.length-1;e>=0;e--)try{await s[e]()}catch(t){console.error(`${i} Cleanup error at index ${e}:`,t)}}}async function w(e,t){const s=t?`[${t}]`:"[ArtifactCleanup]";for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${s} Cleanup error at index ${t}:`,e)}}function v(e){return`${e}__watched`}var b=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function S(e,t){let s;const i=new Promise(((e,i)=>{s=setTimeout((()=>i(new Error(`Timeout: ${t}ms`))),t)}));try{return Promise.race([e,i])}finally{clearTimeout(s)}}var k=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,s){const i=this.get(e);if(!i)return b;if(i.package)return i.package;const r=e,n=m(i.cleanupFunctions,r),a="singleton"!==i.scope||void 0!==i.instance,o={instance:i.instance,error:i.error,ready:a,[s||e]:i.instance,cleanup:n,invalidate:t};return i.package=o,o}invalidatePackage(e){const t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(e,t=!1){const s=this.get(e);if(!s)return;const i=e;"singleton"===s.scope&&(s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.debounceTimer&&(clearTimeout(s.debounceTimer),s.debounceTimer=void 0),s.controller.abort(),await s.streamOnce.current(),s.streamSerializer.close(),s.stream=void 0,s.streamOnce=new p({retry:!0,throws:!0}),t||(s.streamSerializer=new g,s.controller=new AbortController)),await w(s.cleanupFunctions,i),await w(s.disposeFunctions,i),s.cleanupFunctions=[],s.disposeFunctions=[],"singleton"===s.scope&&(s.buildOnce=new p({retry:!0,throws:!0})),s.instance=void 0,s.error=void 0}},I=class{dependencies=new Map;dependents=new Map;registerNode(e){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set)}removeNode(e){if(!this.hasNode(e))return;const t=this.dependencies.get(e);if(t)for(const s of t)this.dependents.get(s)?.delete(e);const s=this.dependents.get(e);if(s)for(const t of s)this.dependencies.get(t)?.delete(e);this.dependencies.delete(e),this.dependents.delete(e)}hasNode(e){return this.dependencies.has(e)}addDependency(e,t){this.registerNode(e),this.registerNode(t),this.dependencies.get(e).add(t),this.dependents.get(t).add(e)}removeDependency(e,t){this.dependencies.get(e)?.delete(t),this.dependents.get(t)?.delete(e)}getDependencies(e){const t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){const t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??A}setDependencies(e,t){this.registerNode(e);const s=this.dependencies.get(e),i=new Set(t);for(const t of s)i.has(t)||this.removeDependency(e,t);for(const t of i)s.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const s=[t],i=new Set([t]),r=new Map;for(;s.length>0;){const n=s.shift();if(n===e){const s=[];let i=e;for(;void 0!==i&&(s.push(i),i!==t);)i=r.get(i);return s.reverse(),s.unshift(e),s}const a=this.dependencies.get(n);if(a)for(const e of a)i.has(e)||(i.add(e),r.set(e,n),s.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const s of t)e.set(s,this.dependencies.get(s)?.size??0);const s=[];for(const[t,i]of e)0===i&&s.push(t);const i=[];for(;s.length>0;){const t=s.shift();i.push(t);const r=this.dependents.get(t);if(r)for(const t of r){const i=(e.get(t)||0)-1;e.set(t,i),0===i&&s.push(t)}}if(i.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return i}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,s){const i=new Set,r=new Set,n=[e];r.add(e),s&&i.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)r.has(e)||(r.add(e),i.add(e),n.push(e))}return i}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const s=Array.from(t).join(", ");return`${String(e)} → [${s||"∅"}]`})).join("\n")}},A=new Set,E=class{graph;constructor(){this.graph=new I}registerNode(e){this.graph.registerNode(e)}removeNode(e){this.graph.removeNode(e)}addDependency(e,t){this.graph.addDependency(e,t)}removeDependency(e,t){this.graph.removeDependency(e,t)}getDependents(e){return Array.from(this.graph.getDependents(e))}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){return Array.from(this.graph.getDependencies(e))}getTransitiveDependents(e){return new Set(Array.from(this.graph.getTransitiveDependents(e,!1)))}setDependencies(e,t){const s=Array.from(t).map((e=>e));this.graph.setDependencies(e,s)}wouldCreateCycle(e,t,s){if(s?.has(t)){const e=Array.from(s),i=e.indexOf(t),r=e.slice(i);return r.push(t),r}const i=this.graph.wouldCreateCycle(e,t);return i||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()}},_=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];var x=class e extends Error{category;constructor(t,s,i){super(t,{cause:i}),this.name="ArtifactError",this.category=s,Object.setPrototypeOf(this,e.prototype)}},O=class extends x{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system"),this.name="ArtifactNotFoundError"}},$=class extends x{constructor(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},D=(new AbortController).signal,C=class{constructor(e,t,s,i,r){this.registry=e,this.cache=t,this.graph=s,this.store=i,this.observer=r}async build(e,t,s){const i=this.cache.get(e);if("singleton"===i?.scope&&i.buildOnce.done())return this.cache.package(e,((t,s)=>this.invalidate(e,t,s)),s);const r=this.registry.getByString(e);if(!r)throw new O(e);const n=t??[];if(n.includes(e))throw new x(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${[...n,e].join(" -> ")}`,"system");n.push(e);let a=i;a||(a=this.createCachedArtifact(r),this.cache.set(e,a));try{if("transient"===a.scope)return this.executeBuild(r,a,n);const i=a;try{await i.buildOnce.do((()=>this.executeBuild(r,i,n)))}catch(i){if(i instanceof $)return this.build(e,t,s);throw i}return i.stream&&i.streamOnce.do(i.stream),this.cache.package(e,((t,s)=>this.invalidate(e,t,s)),s)}finally{n.pop()}}async executeBuild(e,t,s){const i=e.key,r=String(i),n="transient"===t.scope;t.buildCount++,"singleton"===t.scope&&(t.activeDebounceMs=e.debounce??0);const a={cleanupFunctions:[],disposeFunctions:[],capturedArtifactDeps:new Set,capturedStateSelectors:[],dependencyVersions:new Map},o=this.buildContext(e,t,s,r,a),c=await this.runWithRetries(e,o,a.dependencyVersions);if(this.commitResult(i,t,n,c,a),n){const e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[i]:e,cleanup:m(a.cleanupFunctions,r),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${r}"`)}}}buildContext(e,t,s,i,r){const n=e.key,a="transient"===t.scope,{cleanupFunctions:o,disposeFunctions:c,capturedArtifactDeps:h,dependencyVersions:d,capturedStateSelectors:u}=r,l=async(e,t)=>{const r=t?this.computeParamKey(e,t):e;if(r===n)throw new x(`Artifact "${i}" depends on itself.`,"system");const a=this.graph.wouldCreateCycle(n,r);if(a)throw new x(`Adding dependency "${String(r)}" to "${i}" would create a cycle: ${a.join(" -> ")}`,"system");h.add(r);const o=await(t?this.resolveParameterized(e,t):this.build(e,s)),c=this.cache.get(r);return c&&d.set(r,c.version),o},p="singleton"===t.scope?t.controller.signal:D,g=async(e,t)=>{const s=await l(e,t);if(s.error)throw s.error;return s.instance},f=(e,t)=>{const s=function(e,t="."){const s=new Set,i=new Map,r=(e="")=>{if(i.has(e))return i.get(e);const n=new Proxy((()=>{}),{get:(i,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic, arithmetic, or string operations inside a selector.");if(_.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&s.delete(e),s.add(a),r(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions or methods.")}});return i.set(e,n),n};try{e(r())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(s)}(e);return u.push({paths:s,options:t}),e(this.store.get(!0))};return{state:()=>this.store.get(!0),previous:t.instance,signal:p,onCleanup:e=>o.push(e),onDispose:e=>c.push(e),use:e=>e({resolve:l,require:g,select:f}),stream:e=>{if(a)throw new x(`[ArtifactManager] Illegal stream on transient artifact "${i}"`,"system");const s=t,r=async(e,t=void 0)=>{await s.streamSerializer.do((async()=>{void 0!==s.stream&&(s.instance=e,s.error=t,s.version++,this.cache.invalidatePackage(n),await this.processStream(i))}))},o={value:()=>s.instance,get signal(){return s.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>r(e)};s.stream=async()=>{try{const t=await e(o);t&&s.cleanupFunctions.push(t)}catch(e){await r(void 0,e),await this.invalidate(n,!1,!0)}}}}}async runWithRetries(e,t,s){const i=t.signal,r=(e.retries??0)+1;let n=0;for(;n<r;)try{if(i.aborted)throw new $;const a=e.factory(t);let o;if(o=a instanceof Promise?e.timeout?await S(a,e.timeout):await a:a,i.aborted)throw new $;const c=this.detectStaleness(s);if(c){if(n++,s.clear(),n<r)continue;return{ok:!1,error:new x(`Build stale after all retries: dependency "${String(c)}" changed during build.`,"system")}}return{ok:!0,value:o}}catch(e){if(i.aborted||e instanceof $)throw new $;if(e instanceof x)throw e;if(n++,n>=r)return{ok:!1,error:e}}return{ok:!1,error:new Error("Build exhausted retry budget unexpectedly.")}}commitResult(e,t,s,i,r){const{cleanupFunctions:n,disposeFunctions:a,capturedArtifactDeps:o,capturedStateSelectors:c}=r;s||(this.updateDependencyGraph(e,o,c),t.cleanupFunctions=n,t.disposeFunctions=a),i.ok?(t.instance=i.value,t.error=void 0):(t.instance=void 0,t.error=i.error),t.version++,this.cache.invalidatePackage(e)}detectStaleness(e){for(const[t,s]of e){const e=this.cache.get(t);if(e&&e.version!==s)return t}return null}async invalidate(e,t=!1,s=!1){const i=this.cache.get(e);if(!i)return;if("singleton"!==i.scope)return this.executeInvalidation(e,t,s);const r=i;return r.debounceTimer&&(clearTimeout(r.debounceTimer),r.debounceTimer=void 0),!t&&r.activeDebounceMs>0?new Promise(((i,n)=>{r.debounceTimer=setTimeout((()=>{r.debounceTimer=void 0,this.executeInvalidation(e,t,s).then(i).catch(n)}),r.activeDebounceMs)})):this.executeInvalidation(e,t,s)}async executeInvalidation(e,t,s=!1){const i=this.cache.get(e);i&&"singleton"===i.scope&&await i.invalidationSerializer.do((async()=>{i.version++,await this.cache.invalidateInstance(e),await this.cascadeInvalidation(this.graph.iterDependents(e));const r=this.registry.get(e),n=r&&(t||!r.lazy||this.observer.hasWatchers(e))&&!s;n&&await this.build(e).catch((t=>{t instanceof $||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(n||s)&&this.observer.notify(e)}))}async dispose(e){this.cache.get(e)&&(await this.cache.invalidateInstance(e,!0),this.graph.removeNode(e),this.cache.delete(e))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(0===e.size)return;const t=[];for(const s of e)t.push(this.invalidate(s).catch((e=>{console.error(`[ArtifactManager] Cascade failed for "${String(s)}":`,e)})));await Promise.all(t)}updateDependencyGraph(e,t,s){const i=this.cache.get(e);if(!i||"singleton"!==i.scope)return;this.graph.registerNode(e),this.graph.setDependencies(e,t),i.stateDependencies=new Set;for(const{paths:e}of s)for(const t of e)i.stateDependencies.add(t);if(i.stateUnsubscribe&&(i.stateUnsubscribe(),i.stateUnsubscribe=void 0),0===s.length)return;const r=()=>this.invalidate(e),n=new Map;for(const{paths:e,options:t}of s){const s=void 0===t?"undefined":JSON.stringify(t);let i=n.get(s);i||(i={options:t,paths:new Set},n.set(s,i));for(const t of e)i.paths.add(t)}const a=[];for(const{options:e,paths:t}of n.values()){if(0===t.size)continue;const s=Array.from(t);void 0===e?a.push(this.store.watch(s,r)):a.push(this.store.watch(s,r,e))}0===a.length?i.stateUnsubscribe=void 0:1===a.length?i.stateUnsubscribe=a[0]:i.stateUnsubscribe=()=>{for(const e of a)e()}}createCachedArtifact(e){return"transient"===e.scope?{scope:"transient",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0}:{scope:"singleton",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce?e.debounce:0,controller:new AbortController,buildOnce:new p({retry:!0,throws:!0}),streamOnce:new p({retry:!0,throws:!0}),streamSerializer:new g({yieldMode:"microtask"}),invalidationSerializer:new g({yieldMode:"macrotask"})}}resolveStatic(e){if(!this.registry.has(e))throw new O(e);return this.build(e)}async resolveParameterized(e,t){if(!this.registry.has(e))throw new O(String(e));const s=this.registry.get(e);if(!s.paramKey)throw new x(`Artifact "${String(e)}" is not parameterized.`,"external");const i=s.paramKey(t),r=this.registry.getByString(i);if(r&&!r.paramKey&&!r.virtual)throw new x(`Parameterized artifact "${String(e)}" with params ${JSON.stringify(t)} resolves to key "${i}" which is already registered as a static artifact.`,"system");return this.registry.hasString(i)||this.registry.setVirtual(i,{key:i,factory:e=>s.factory({...e,params:t}),scope:s.scope,lazy:s.lazy,timeout:s.timeout,retries:s.retries,debounce:s.debounce,virtual:!0}),this.build(i,void 0,e)}computeParamKey(e,t){const s=this.registry.get(e);if(!s.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);return s.paramKey(t)}},R=class{constructor(e,t,s){this.registry=e,this.cache=t,this.container=s}listeners=new Map;watchers=new Map;watch(e,t=6e4){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,s=6e4){const i=this.registry.get(e);if(!i.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);const r=i.paramKey(t);return this.watchForKey(r,i,s,t)}watchForKey(e,t,s,i){const r="transient"===t.scope,n=r?v(e):e,a=this.watchers.get(n);if(a)return a.observer;const o=new y((async()=>{!r&&void 0===i||this.registry.hasString(e)||this.registry.setVirtual(e,{key:e,factory:r?t.factory:e=>t.factory({...e,params:i}),scope:r?"singleton":t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})}),(async()=>{r||void 0!==i?(await this.registry.unregister(n).catch((()=>{})),this.cache.delete(n),this.watchers.delete(n)):this.cache.invalidatePackage(n),this.listeners.delete(n)}),{gracePeriod:r&&void 0===i?"sync":s});let c;const h={id:n,get count(){return o.subscribers},get:(t=!1)=>0!==o.subscribers||t?this.cache.package(n,((e,t)=>this.container.invalidate(n,e,t)),e):b,resolve:()=>c||(c=(async()=>{await o.acquire();try{return await this.container.resolve(n)}finally{o.release(),c=void 0}})(),c),subscribe:(e,t=!0)=>{const s=()=>e(h.get());return o.acquire().then((()=>{this.container.resolve(n).then((()=>{this.listeners.has(n)||this.listeners.set(n,new Set),t&&s(),this.listeners.get(n).add(s)}))})).catch((e=>{console.error(`[ArtifactObserver] Resolution failed for "${n}":`,e),this.listeners.get(n)?.add(s)})),()=>{this.listeners.get(n)?.delete(s),o.release()}}};return this.watchers.set(n,{resource:o,observer:h}),h}evictWatcher(e){[e,v(e)].forEach((e=>{const t=this.watchers.get(e);t&&(t.resource.forceCleanup(),this.watchers.delete(e))}))}notify(e){const t=this.listeners.get(e);if(t&&0!==t.size)for(const s of t)try{s()}catch(t){console.error(`[ArtifactObserver] Listener error for "${e}":`,t)}}hasWatchers(e){return this.watchers.has(e)||this.watchers.has(v(e))}getWatcherCount(e){const t=this.watchers.get(e)||this.watchers.get(v(e));return t?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}},N=class{artifacts=new Map;register({key:e,factory:t,lazy:s,...i}){const{scope:r,...n}=i,a={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===s||s,...n};return this.artifacts.set(e,a),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw new O(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()}},P=class{registry;cache;graph;manager;observer;store;constructor(e){this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t)},this.registry=new N,this.cache=new k,this.graph=new E,this.observer=new R(this.registry,this.cache,this),this.manager=new C(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const s=t,i=this.registry.get(s),r=this.cache.get(s);if(!i)return;let n="idle";r&&("singleton"===r.scope&&void 0!==r.debounceTimer?n="debouncing":"singleton"===r.scope&&r.buildOnce.running()?n="building":r.error?n="error":void 0!==r.instance&&(n="active")),e.push({id:s,scope:i.scope??"singleton",status:n,dependencies:this.graph.getDependencies(s).map((e=>String(e))),dependents:this.graph.getDependents(s).map((e=>String(e))),stateDependencies:"singleton"===r?.scope?Array.from(r.stateDependencies):[],buildCount:r?.buildCount??0})})),e}register(e){const{key:t}=e,s=t;this.registry.has(t)&&(console.warn(`[ArtifactContainer] Overwriting "${s}".`),this.manager.dispose(t).catch((e=>{console.error(`[ArtifactContainer] Failed to dispose existing artifact "${s}":`,e)}))),this.registry.register(e),this.graph.registerNode(t);const i=e.scope??"singleton";return(e.lazy??!0)||"singleton"!==i||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${s}":`,e)})),()=>this.unregister(t)}has(e){return this.registry.has(e)}async unregister(e,t){const s=void 0!==t?this.manager.computeParamKey(e,t):e;await this.manager.dispose(s),await this.registry.unregister(s),this.observer.evictWatcher(s)}async resolve(e,t){return void 0===t?this.manager.resolveStatic(e):this.manager.resolveParameterized(e,t)}async require(e,t){const s=await this.resolve(e,t);if(s.error)throw s.error;return s.instance}watch(e,t,s){return void 0===t?this.observer.watch(e,s):this.observer.watchParameterized(e,t,s)}peek(e,t){const s=void 0!==t?this.manager.computeParamKey(e,t):e;return this.cache.get(s)?.instance}async invalidate(e,t){const s=t?.params,i=t?.replace??!1,r=void 0!==s?this.manager.computeParamKey(e,s):e;return this.manager.invalidate(r,i)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){const e=this.registry.keys();await Promise.allSettled(e.map((e=>this.manager.dispose(e).catch((t=>{console.error(`[ArtifactContainer] Failed to dispose artifact "${String(e)}":`,t)}))))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear()}};function M(e){return"object"==typeof e&&null!==e&&"pause"in e}var T="__pipeline_data__";var L={info:()=>{},error:()=>{}},K=class{constructor(e,t,s,i,r,n,a,o,c,h,d,u,l,p){this.pipeline=t,this.entry=s,this.store=i,this.container=r,this.keyPrefix=n,this.bus=a,this.parentPath=o,this.controller=c,this.once=h,this.logger=d,this.definitionId=u,this.index=l,this.factory=p,this.id=e}id;on(e,t){return this.bus.on(e,t)}abort(){this.controller.abort()}async run(){const e=await this.once.do((()=>this.execute()));return void 0!==e.error?c(new r({code:s.INTERNAL_ERROR.code,message:`Unexpected throw escaped run(): ${V(e.error)}`,operation:`pipeline:${this.pipeline.id}`,cause:e.error})):e.value}async execute(){this.bus.emit("pipeline:start",{path:this.parentPath,pipelineId:this.pipeline.id,pipelineLabel:this.pipeline.label,runId:this.id}),this.logger.info(`Pipeline start: ${this.pipeline.id} [${this.id}]`);const e=this.resolveEntryStage();if(!e.ok)return this.failPipeline(e.error);const{stageMap:t,orderedStages:i,stageOrderIndex:n}=this.index;let a=e.value,c=!0;for(;;){if(this.controller.signal.aborted){const e=new r({code:s.OPERATION_ABORTED.code,message:`Run aborted before stage "${a.label}".`,operation:`stage:${a.id}`});return this.failPipeline(e)}const e=c?this.entry:void 0;c=!1;const h=await this.executeStage(a,e);if(!h.ok)return this.failPipeline(h.error);const d=h.value,u="pause"===d.kind?void 0:d.nextInstruction,l=n.get(a.id)??-1,p=void 0!==i[l+1],g="pause"===d.kind?"pause":null===u?"terminate":"string"==typeof u?"jump":p?"advance":"natural-end";if(this.bus.emit("router:evaluated",{path:this.parentPath,stageId:a.id,stageLabel:a.label,runId:this.id,instruction:u,interpretation:g}),"pause"===d.kind){const{checkpoint:e}=d,t=this.store.get(!0);return this.logger.info(`Pipeline paused: ${this.pipeline.id} [${this.id}] at stage "${e.pausedAtStageId}"`),this.bus.emit("pipeline:paused",{path:this.parentPath,pipelineId:this.pipeline.id,pipelineLabel:this.pipeline.label,runId:this.id,checkpoint:e,finalState:t}),o({status:"paused",runId:this.id,finalState:t,checkpoint:e})}if(null===u)break;if("string"==typeof u){const e=t.get(u);if(!e){const e=new r({code:s.INVALID_COMMAND.code,message:`Router on stage "${a.label}" returned unknown stageId: "${u}"`,operation:`stage:${a.id}`});return this.failPipeline(e)}a=e;continue}const f=i[l+1];if(!f)break;a=f}const h=this.store.get(!0);return this.logger.info(`Pipeline succeeded: ${this.pipeline.id} [${this.id}]`),this.bus.emit("pipeline:success",{path:this.parentPath,pipelineId:this.pipeline.id,pipelineLabel:this.pipeline.label,runId:this.id,finalState:h}),o({status:"succeeded",runId:this.id,finalState:h})}resolveEntryStage(){const{stageMap:e,orderedStages:t}=this.index;if(this.entry?.stage){const t=e.get(this.entry.stage);return t?o(t):c(new r({code:s.INVALID_COMMAND.code,message:`Entry stage "${this.entry.stage}" not found.`,operation:`pipeline:${this.pipeline.id}`}))}const i=t[0];return i?o(i):c(new r({code:s.INVALID_COMMAND.code,message:"Pipeline has no stages.",operation:`pipeline:${this.pipeline.id}`}))}async executeStage(e,t){const s=e.pipelines&&e.pipelines.length>0?"pipelines":"steps",i=[...this.parentPath,{kind:"stage",id:e.id,label:e.label}];this.bus.emit("stage:start",{path:this.parentPath,stageId:e.id,stageLabel:e.label,runId:this.id,mode:s});const r="pipelines"===s?await this.executePipelinesStage(e,i,t):await this.executeStepsStage(e,i,t);return r.ok?"pause"===r.value.kind?this.bus.emit("stage:paused",{path:this.parentPath,stageId:e.id,stageLabel:e.label,runId:this.id,checkpoint:r.value.checkpoint}):this.bus.emit("stage:success",{path:this.parentPath,stageId:e.id,stageLabel:e.label,runId:this.id,nextInstruction:r.value.nextInstruction}):this.bus.emit("stage:failure",{path:this.parentPath,stageId:e.id,stageLabel:e.label,runId:this.id,error:r.error}),r}async executeStepsStage(e,t,i){const n=Object.values(e.steps??{});if(0===n.length){this.logger.info(`Stage "${e.label}" has no steps — skipping.`);const t=B(e.router,this.store.get(!0),{});return o(U(t))}if(this.controller.signal.aborted)return c(new r({code:s.OPERATION_ABORTED.code,message:`Aborted before resolving steps in stage "${e.label}".`,operation:`stage:${e.id}`}));const a=void 0!==i?.step?n.filter((e=>e.id===i.step)):n;if(void 0!==i?.step&&0===a.length)return c(new r({code:s.INVALID_COMMAND.code,message:`Entry step "${i.step}" not found in stage "${e.label}".`,operation:`stage:${e.id}`}));for(const e of a)this.bus.emit("step:start",{path:t,stepId:e.id,stepLabel:e.label,runId:this.id});const h=await Promise.all(a.map((async t=>({step:t,result:await this.container.resolve(z(this.keyPrefix,e.id,t.id))})))),d={};for(const{step:e,result:i}of h)i.ready?(this.bus.emit("step:success",{path:t,stepId:e.id,stepLabel:e.label,runId:this.id}),d[e.id]=o(i.instance)):(this.bus.emit("step:failure",{path:t,stepId:e.id,stepLabel:e.label,runId:this.id,error:i.error}),d[e.id]=c(new r({code:s.BACKEND_ERROR.code,message:V(i.error)})));const u=h.find((({result:e})=>!e.ready));if(u){const e=u.result.error;return c(new r({code:s.BACKEND_ERROR.code,message:`Step "${u.step.label}" failed: ${V(e)}`,operation:`step:${u.step.id}`,cause:e}))}const l=h.map((({result:e})=>e.instance)).filter((e=>null!=e));let p;try{await this.store.transaction((async()=>{for(const e of l)await this.store.set(e);const t=B(e.router,this.store.get(!0),d);if(M(t)){const s={runId:this.id,pipelineId:this.definitionId,resumeAt:{stage:t.pause},pausedAtStageId:e.id,pausedAtStageLabel:e.label,pausedOn:(new Date).toISOString()};await j(this.store,s),p={kind:"pause",checkpoint:s}}else p=U(t)}),{flush:!0})}catch(t){return c(new r({code:s.CONCURRENCY_ERROR.code,message:`Transaction failed during stage "${e.label}": ${V(t)}`,operation:`stage:${e.id}`,cause:t}))}return o(p)}async executePipelinesStage(e,t,i){const n=e.pipelines,a=void 0!==i?.pipeline?(()=>{const{index:e}=i.pipeline,t=n[e];return t?[{subPipeline:t,originalIndex:e}]:[]})():n.map(((e,t)=>({subPipeline:e,originalIndex:t})));if(void 0!==i?.pipeline&&0===a.length)return c(new r({code:s.INVALID_COMMAND.code,message:`Entry sub‑pipeline index ${i.pipeline.index} out of bounds.`,operation:`stage:${e.id}`}));this.bus.emit("subpipeline:fork",{path:t,stageId:e.id,stageLabel:e.label,runId:this.id,subPipelineIds:a.map((({subPipeline:e})=>e.id))});const h=a.map((({subPipeline:s,originalIndex:r})=>{const n=void 0!==i?.pipeline?{stage:i.pipeline.stage,step:i.pipeline.step}:void 0,a=function(e,t,s){const i=`${t}:pipeline-${s}`;return e?`${e}:${i}`:i}(this.keyPrefix,e.id,r);return{subPipeline:s,originalIndex:r,ctx:this.factory.buildRunContext(this.id,s,n,this.store,this.bus,t,this.container,a)}})),d=()=>{h.forEach((({ctx:e})=>e.abort()))};this.controller.signal.addEventListener("abort",d,{once:!0});try{if(this.controller.signal.aborted)return d(),c(new r({code:s.OPERATION_ABORTED.code,message:this.controller.signal.reason,operation:`stage:${e.id}`}));const i=await Promise.all(h.map((({ctx:e})=>e.run()))),n={};for(let e=0;e<a.length;e++)n[a[e].subPipeline.id]=i[e];this.bus.emit("subpipeline:join",{path:t,stageId:e.id,stageLabel:e.label,runId:this.id,results:n});const u=i.findIndex((e=>!e.ok||"failed"===e.value.status));if(-1!==u){const t=a[u].subPipeline.id,n=i[u],o=n.ok?n.value.error:n.error;return c(new r({code:s.BACKEND_ERROR.code,message:`Sub‑pipeline "${t}" failed: ${V(o)}`,operation:`stage:${e.id}`,cause:o}))}const l=i.findIndex((e=>e.ok&&"paused"===e.value.status));if(-1!==l){const t=i[l].value,{checkpoint:n}=t,h={runId:this.id,pipelineId:this.definitionId,resumeAt:{stage:e.id,pipeline:{index:a[l].originalIndex,stage:n.resumeAt.stage,step:n.resumeAt.step}},pausedAtStageId:e.id,pausedAtStageLabel:e.label,pausedOn:(new Date).toISOString()};try{await this.store.transaction((async()=>{await j(this.store,h)}),{flush:!0})}catch(t){return c(new r({code:s.CONCURRENCY_ERROR.code,message:`Failed to write parent pause checkpoint for stage "${e.label}".`,operation:`stage:${e.id}`,cause:t}))}return o({kind:"pause",checkpoint:h})}let p;try{await this.store.transaction((async()=>{const t=B(e.pipelinesRouter,this.store.get(!0),n);if(M(t)){const s={runId:this.id,pipelineId:this.definitionId,resumeAt:{stage:t.pause},pausedAtStageId:e.id,pausedAtStageLabel:e.label,pausedOn:(new Date).toISOString()};await j(this.store,s),p={kind:"pause",checkpoint:s}}else p=U(t)}),{flush:!0})}catch(t){return c(new r({code:s.CONCURRENCY_ERROR.code,message:`Transaction failed evaluating router for stage "${e.label}": ${V(t)}`,operation:`stage:${e.id}`,cause:t}))}return o(p)}finally{this.controller.signal.removeEventListener("abort",d)}}failPipeline(e){return this.bus.emit("pipeline:failure",{path:this.parentPath,pipelineId:this.pipeline.id,pipelineLabel:this.pipeline.label,runId:this.id,error:e}),c(e)}};function F(e){const t=[...e.stages].sort(((e,t)=>e.order-t.order)),s=new Map,i=new Map;for(let e=0;e<t.length;e++){const r=t[e];s.set(r.id,r),i.set(r.id,e)}return{stageMap:s,orderedStages:t,stageOrderIndex:i}}function z(e,t,s){return e?`${e}:${t}:${s}`:`${t}:${s}`}function B(e,t,s){return e?e(t,s):void 0}function U(e){return{kind:"advance",nextInstruction:e}}function V(e){return e instanceof Error?e.message:String(e)}async function j(e,t){const s=e,i=t.pipelineId,r=t.runId,n=s.get(!0)[T]??{},a={...n,[i]:{...n[i]??{},[r]:t}};await s.set({[T]:a})}exports.PIPELINE_DATA_KEY=T,exports.Pipeline=class{steps=new Map;globalBus=e.createEventBus();serializer=new g;executions=new Map;constructor(e){e&&e.forEach(((e,t)=>{(Array.isArray(e)?e:[e]).forEach((e=>this.steps.set(e.key,{...e,order:t})))}))}getSteps(){return this.steps}step(e){return this.steps.set(e.key,e),this}on(e,t){return this.globalBus.subscribe(e,t)}prepare(e,t,s,i){return new f(this,e,t,s?.signal,i)}async execute(e,t,s){const i=s?.disableDeduplication?`${e}:${Date.now()}:${Math.random()}`:this.getDedupeKey(e,t);let r=this.executions.get(i);r||(r=new p({retry:!0,throws:!1}),this.executions.set(i,r));const n=await r.do((async()=>{const i=await this.serializer.do((async()=>{const i=this.prepare(e,t,{signal:s?.signal},this.globalBus);return await i.run()}));if(i.error)throw i.error;return i.value})).finally((()=>{setTimeout((()=>this.executions.delete(i)),0)}));return n.error?c(n.error):n.value}getRegisteredSteps(){return Array.from(this.steps.keys())}validate(){const e=[];return 0===this.steps.size&&e.push("Pipeline has no registered steps"),e}destroy(){this.steps.clear(),this.globalBus.clear(),this.executions.clear()}groupByOrder(){const e=new Map;for(const t of this.steps.values()){const s=e.get(t.order)??[];s.push(t),e.set(t.order,s)}return e}getDedupeKey(e,t){try{return`${e}:${JSON.stringify(this.sortObjectKeys(t))}`}catch{return`${e}:${Date.now()}:${Math.random()}`}}sortObjectKeys(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map((e=>this.sortObjectKeys(e)));const t={};return Object.keys(e).sort().forEach((s=>{t[s]=this.sortObjectKeys(e[s])})),t}},exports.PipelineEngine=class{constructor(e,t){this.definition=e,this.logger=t.logger??L,this.storeFactory=t.storeFactory,this.initialStateFactory=t.initialStateFactory,this.index=F(e)}logger;storeFactory;initialStateFactory;index;async prepare(e,s){const i=s??t.v7(),r=await this.storeFactory(i);await r.ready();const n=this.initialStateFactory?.()??{};return await r.set(n),this.logger.info(`Prepared new run "${i}" for pipeline "${this.definition.id}"`),this.buildRunContext(i,this.definition,e,r,void 0,[])}async resume(e){const t=await this.storeFactory(e),i=function(e,t,s){const i=e,r=i.get(!0)[T],n=r?.[t]?.[s];return n??null}(t,this.definition.id,e);return i?i.pipelineId!==this.definition.id?c(new r({code:s.INVALID_COMMAND.code,message:`Checkpoint runId "${e}" belongs to pipeline "${i.pipelineId}", not "${this.definition.id}".`,operation:"resume"})):(this.logger.info(`Resuming pipeline "${this.definition.id}" [${e}] from stage "${i.pausedAtStageId}"`),o(this.buildRunContext(e,this.definition,i.resumeAt,t,void 0,[]))):c(new r({code:s.NOT_FOUND.code,message:`No checkpoint found for runId "${e}".`,operation:"resume"}))}buildRunContext(t,s,i,r,n,a,o,c){const h=void 0===o,d=h?new P(r):o,u=c??"",l=new AbortController;!function(e,t,s,i){for(const r of t.stages)if(r.steps)for(const t of Object.values(r.steps)){const n={runId:i.runId,pipelineId:i.pipelineId,stageId:r.id,stepId:t.id,signal:i.signal};e.register({key:z(s,r.id,t.id),factory:e=>t.action(e,n),scope:t.scope,...void 0!==t.timeout&&{timeout:t.timeout},...void 0!==t.retries&&{retries:t.retries}})}}(d,s,u,{runId:t,pipelineId:s.id,signal:l.signal});const g=function(e,t){return{emit(s,i){e.emit({name:s,payload:i}),t?.emit(s,i)},on:(t,s)=>e.subscribe(t,s)}}(e.createEventBus(),n),f=new p({retry:!1,throws:!1}),y=h?this.index:F(s);return new K(t,s,i,r,d,u,g,a,l,f,this.logger,this.definition.id,y,this)}},exports.SequentialExecutionContext=f,exports.isPauseInstruction=M;
|
|
1
|
+
"use strict";var e=require("@asaidimu/utils-events"),t=require("uuid"),s={VALIDATION_FAILED:{code:"VAL-001",name:"VALIDATION_FAILED",description:"Input validation failed due to one or more invalid fields",category:"validation",httpStatus:400,logLevel:"warn"},REQUIRED_FIELD_MISSING:{code:"VAL-002",name:"REQUIRED_FIELD_MISSING",description:"A required field was not provided in the request",category:"validation",httpStatus:400,logLevel:"warn"},INVALID_FORMAT:{code:"VAL-003",name:"INVALID_FORMAT",description:"Field value does not match expected format",category:"validation",httpStatus:400,logLevel:"warn"},NOT_FOUND:{code:"DB-001-NF",name:"NOT_FOUND",description:"The requested resource could not be found",category:"database",httpStatus:404,logLevel:"info",action:"Verify the resource identifier exists before accessing"},DUPLICATE_KEY:{code:"DB-002-DUP",name:"DUPLICATE_KEY",description:"A unique constraint violation occurred",category:"database",httpStatus:409,logLevel:"warn",action:"Check if the resource already exists before creation"},RESOURCE_LOCKED:{code:"DB-003-LOCK",name:"RESOURCE_LOCKED",description:"The resource is currently locked by another operation",category:"database",httpStatus:409,logLevel:"warn",action:"Retry the operation after a brief delay"},PERMISSION_DENIED:{code:"AUTH-001-DENIED",name:"PERMISSION_DENIED",description:"The authenticated user lacks permission for this operation",category:"auth",httpStatus:403,logLevel:"warn",action:"Check user roles and permissions"},UNAUTHENTICATED:{code:"AUTH-002-UNAUTH",name:"UNAUTHENTICATED",description:"Authentication is required for this operation",category:"auth",httpStatus:401,logLevel:"info",action:"Provide valid authentication credentials"},INVALID_COMMAND:{code:"BUS-001",name:"INVALID_COMMAND",description:"The command or operation is invalid for the current state",category:"business",httpStatus:400,logLevel:"warn"},OPERATION_ABORTED:{code:"BUS-002-ABORT",name:"OPERATION_ABORTED",description:"The operation was explicitly aborted",category:"business",httpStatus:409,logLevel:"info"},INTERNAL_ERROR:{code:"SYS-001",name:"INTERNAL_ERROR",description:"An unexpected internal error occurred",category:"system",httpStatus:500,logLevel:"error",action:"Check system logs for stack traces and diagnostic information"},BACKEND_ERROR:{code:"SYS-002",name:"BACKEND_ERROR",description:"An error occurred in a backend service",category:"system",httpStatus:502,logLevel:"error"},CONCURRENCY_ERROR:{code:"CON-001",name:"CONCURRENCY_ERROR",description:"A concurrency conflict occurred during the operation",category:"concurrency",httpStatus:409,logLevel:"warn",action:"Retry the operation with updated data"}},i=new Map;var r=class e extends Error{code;codeMetadata;severity;path;operation;issues;cause;constructor(t){const r={...function(e){const t=Object.values(s).find((t=>t.code===e));if(t)return t;return i.get(e)||{code:e,name:e.replace(/-/g,"_"),description:`Unknown error: ${e}`,category:"custom",httpStatus:500,logLevel:"error",action:"Check if this error code is properly registered or handle as unknown error"}}(t.code),...t.metadata,code:t.code};super(t.message??r.description),this.name="SystemError",this.code=t.code,this.codeMetadata=r,this.severity=t.severity??"error",this.path=t.path,this.operation=t.operation,this.issues=t.issues??[],this.cause=t.cause,Object.setPrototypeOf(this,e.prototype),Error.captureStackTrace&&Error.captureStackTrace(this,e)}withPath(t){return new e({code:this.code,message:this.message,severity:this.severity,path:t,operation:this.operation,issues:this.issues,cause:this.cause,metadata:this.codeMetadata})}withOperation(t){return new e({code:this.code,message:this.message,severity:this.severity,path:this.path,operation:t,issues:this.issues,cause:this.cause,metadata:this.codeMetadata})}withIssue(t){return new e({code:this.code,message:this.message,severity:this.severity,path:this.path,operation:this.operation,issues:[...this.issues,t],cause:this.cause,metadata:this.codeMetadata})}withIssues(t){return new e({code:this.code,message:this.message,severity:this.severity,path:this.path,operation:this.operation,issues:[...this.issues,...t],cause:this.cause,metadata:this.codeMetadata})}withCause(t){return new e({code:this.code,message:this.message,severity:this.severity,path:this.path,operation:this.operation,issues:this.issues,cause:t,metadata:this.codeMetadata})}getHttpStatus(){return this.codeMetadata.httpStatus}toLogEntry(){return{name:this.name,code:this.code,category:this.codeMetadata.category,message:this.message,path:this.path,operation:this.operation,issues:this.issues,cause:this.cause instanceof Error?this.cause.message:this.cause,stack:this.stack,timestamp:(new Date).toISOString()}}toString(){let e=`[${this.code}] ${this.message} (${this.codeMetadata.category})`;return this.path&&(e+=` at '${this.path}'`),this.operation&&(e+=` during '${this.operation}'`),this.issues.length>0&&(e+="\nIssues:\n"+this.issues.map(((e,t)=>` ${t+1}. ${e.message} [${e.code}]`)).join("\n")),this.cause&&(e+=`\nCause: ${this.cause instanceof Error?this.cause.message:String(this.cause)}`),e}},n="SYS-001",a=(e,t)=>new r({code:n,message:t,cause:e}),o=e=>({ok:!0,value:e}),c=e=>({ok:!1,error:e}),h=class e extends r{constructor(t,s){super({code:"SYNC_ERROR",message:t,cause:s}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},d=class e extends h{constructor(t){super(`[ArtifactContainer] Operation timed out: ${t}`),this.name="TimeoutError",Object.setPrototypeOf(this,e.prototype)}},u=class e extends h{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)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const s=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await s;let i;await Promise.race([s.then((()=>clearTimeout(i))),new Promise(((s,r)=>{i=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),r(new d("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},p=class{mutex=new l({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}resolve(e){if(this._done)throw new Error("Cannot resolve: operation is already completed.");if(this.running())throw new 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){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}running(){return null!==this.promise&&!this.done()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,s="Operation timed out"){if(null==t)return e;let i;return Promise.race([e.then((e=>(clearTimeout(i),e))),new Promise(((e,r)=>{i=setTimeout((()=>r(new d(s))),t)}))])}},g=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 u};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let s,i=null;try{if(this._done)throw new u;i=await e(),this._lastValue=i,this._lastError=void 0,this._hasRun=!0}catch(e){s=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:i,error:s}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},f=class{constructor(t,s,i,r,n){this.pipeline=t,this.stepKey=s,this.params=i,r&&(r.aborted&&this.controller.abort(),r.addEventListener("abort",(()=>this.controller.abort()))),this.localBus=n??e.createEventBus()}id=Math.random().toString(36).substring(2,9);localBus;controller=new AbortController;once=new p({retry:!1,throws:!1});get signal(){return this.controller.signal}on(e,t){return this.localBus.subscribe(e,t)}abort(){this.controller.abort()}async run(){const{value:e,error:t}=await this.once.do((()=>this._run()));return t?c(t):e}async _run(){const e=this.pipeline.getSteps().get(this.stepKey);if(!e)return{ok:!1,error:new r({code:s.INVALID_COMMAND.code,message:`No step registered with key "${this.stepKey}"`,operation:this.stepKey})};if(this.signal.aborted)return this.failCancelled("Pipeline execution aborted before initialization",this.stepKey);const t=this.pipeline.groupByOrder(),i=Array.from(t.entries()).sort((([e],[t])=>e-t)),n=e.order;this.emit("start",{stepKey:this.stepKey,executionId:this.id});let a={[this.stepKey]:this.params},o=a,c=!0;for(const[e,t]of i){if(e<n)continue;if(this.signal.aborted)return this.failCancelled(`Pipeline runtime aborted at stage ${e}`,this.stepKey);const s=c?t.filter((e=>e.key===this.stepKey)):t;if(c=!1,0===s.length)continue;const i=await this.runStage(s,a);if(!i.ok)return i;o=i.value,a={...a,...o},this.emit("stage:success",{order:e,executionId:this.id,carry:o})}return this.emit("terminate",{carry:o,executionId:this.id}),{ok:!0,value:o}}async runStage(e,t){const s=await Promise.all(e.map((async e=>{try{if(this.signal.aborted)return{step:e,result:this.failCancelled("Aborted mid-flight execution sequence",e.key)};const s=await e.action(t,this.signal);return{step:e,result:s}}catch(t){return{step:e,result:{ok:!1,error:t instanceof r?t:a(t,t instanceof Error?t.message:"Unexpected exception raised during step run")}}}}))),i={};let n=null;for(const{step:e,result:t}of s)if(t.ok)this.emit("step:success",{stepKey:e.key,executionId:this.id,result:t.value}),i[e.key]=t.value;else{const s=t.error.withOperation(e.key);this.emit("step:failure",{stepKey:e.key,executionId:this.id,error:s}),n||(n={ok:!1,error:s},this.emit("failure",{stepKey:e.key,executionId:this.id,error:s}))}return n||{ok:!0,value:i}}emit(e,t){this.localBus.emit({name:e,payload:t})}failCancelled(e,t){return{ok:!1,error:new r({code:"CANCELLED",message:e,operation:t})}}},y=class{constructor(e,t,s={}){this.factory=e,this.onCleanup=t,this.options=s}_count=0;init=new p({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;const e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){this._count<=0?console.warn("SharedResource.release() called, but count is already 0."):(this._count--,0===this._count&&this.scheduleCleanup())}peek(){const e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,void 0!==this.cleanupTimer&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){const e=this.options.gracePeriod??"microtask";if("sync"!==e)return"microtask"===e?(this.pendingMicrotask=!0,void queueMicrotask((()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())}))):void(this.cleanupTimer=setTimeout((()=>{this.cleanupTimer=void 0,this._count>0||this.executeCleanup()}),e));this.executeCleanup()}executeCleanup(){const e=this.init.peek();try{this.onCleanup(e.value)}catch(e){console.error("[SharedResource] Error during cleanup callback:",e)}this.init.running()||this.init.reset()}};function m(e,t){if(!e.length)return;const s=e.slice(),i=t?`[${t}]`:"[ArtifactCleanup]";return async()=>{for(let e=s.length-1;e>=0;e--)try{await s[e]()}catch(t){console.error(`${i} Cleanup error at index ${e}:`,t)}}}async function w(e,t){const s=t?`[${t}]`:"[ArtifactCleanup]";for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){console.error(`${s} Cleanup error at index ${t}:`,e)}}function v(e){return`${e}__watched`}var b=Object.freeze({instance:void 0,error:void 0,ready:!1,cleanup:void 0,invalidate:async(e,t)=>{}});function S(e,t){let s;const i=new Promise(((e,i)=>{s=setTimeout((()=>i(new Error(`Timeout: ${t}ms`))),t)}));try{return Promise.race([e,i])}finally{clearTimeout(s)}}async function k(e){const t=(new TextEncoder).encode(e),s=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(s)).map((e=>e.toString(16).padStart(2,"0"))).join("")}var I=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,s){const i=this.get(e);if(!i)return b;if(i.package)return i.package;const r=e,n=m(i.cleanupFunctions,r),a="singleton"!==i.scope||void 0!==i.instance,o={instance:i.instance,error:i.error,ready:a,[s||e]:i.instance,cleanup:n,invalidate:t};return i.package=o,o}invalidatePackage(e){const t=this.get(e);t&&(t.package=void 0)}async invalidateInstance(e,t=!1){const s=this.get(e);if(!s)return;const i=e;"singleton"===s.scope&&(s.stateUnsubscribe&&(s.stateUnsubscribe(),s.stateUnsubscribe=void 0),s.debounceTimer&&(clearTimeout(s.debounceTimer),s.debounceTimer=void 0),s.controller.abort(),await s.streamOnce.current(),s.streamSerializer.close(),s.stream=void 0,s.streamOnce=new p({retry:!0,throws:!0}),t||(s.streamSerializer=new g,s.controller=new AbortController)),await w(s.cleanupFunctions,i),await w(s.disposeFunctions,i),s.cleanupFunctions=[],s.disposeFunctions=[],"singleton"===s.scope&&(s.buildOnce=new p({retry:!0,throws:!0})),s.instance=void 0,s.error=void 0}},A=class{dependencies=new Map;dependents=new Map;registerNode(e){this.dependencies.has(e)||this.dependencies.set(e,new Set),this.dependents.has(e)||this.dependents.set(e,new Set)}removeNode(e){if(!this.hasNode(e))return;const t=this.dependencies.get(e);if(t)for(const s of t)this.dependents.get(s)?.delete(e);const s=this.dependents.get(e);if(s)for(const t of s)this.dependencies.get(t)?.delete(e);this.dependencies.delete(e),this.dependents.delete(e)}hasNode(e){return this.dependencies.has(e)}addDependency(e,t){this.registerNode(e),this.registerNode(t),this.dependencies.get(e).add(t),this.dependents.get(t).add(e)}removeDependency(e,t){this.dependencies.get(e)?.delete(t),this.dependents.get(t)?.delete(e)}getDependencies(e){const t=this.dependencies.get(e);return t?new Set(t):new Set}getDependents(e){const t=this.dependents.get(e);return t?new Set(t):new Set}iterDependents(e){return this.dependents.get(e)??_}setDependencies(e,t){this.registerNode(e);const s=this.dependencies.get(e),i=new Set(t);for(const t of s)i.has(t)||this.removeDependency(e,t);for(const t of i)s.has(t)||this.addDependency(e,t)}wouldCreateCycle(e,t){if(e===t)return[e,t];const s=[t],i=new Set([t]),r=new Map;for(;s.length>0;){const n=s.shift();if(n===e){const s=[];let i=e;for(;void 0!==i&&(s.push(i),i!==t);)i=r.get(i);return s.reverse(),s.unshift(e),s}const a=this.dependencies.get(n);if(a)for(const e of a)i.has(e)||(i.add(e),r.set(e,n),s.push(e))}return null}topologicalSort(){const e=new Map,t=Array.from(this.dependencies.keys());for(const s of t)e.set(s,this.dependencies.get(s)?.size??0);const s=[];for(const[t,i]of e)0===i&&s.push(t);const i=[];for(;s.length>0;){const t=s.shift();i.push(t);const r=this.dependents.get(t);if(r)for(const t of r){const i=(e.get(t)||0)-1;e.set(t,i),0===i&&s.push(t)}}if(i.length!==t.length)throw new Error("Cycle detected in graph; topological sort impossible.");return i}getTransitiveDependencies(e,t=!1){return this.bfs(e,"dependencies",t)}getTransitiveDependents(e,t=!1){return this.bfs(e,"dependents",t)}bfs(e,t,s){const i=new Set,r=new Set,n=[e];r.add(e),s&&i.add(e);const a="dependencies"===t?this.dependencies:this.dependents;for(;n.length>0;){const e=n.shift(),t=a.get(e);if(t)for(const e of t)r.has(e)||(r.add(e),i.add(e),n.push(e))}return i}getAllNodes(){return Array.from(this.dependencies.keys())}size(){return this.dependencies.size}clear(){this.dependencies.clear(),this.dependents.clear()}toDebugString(){return Array.from(this.dependencies.entries()).map((([e,t])=>{const s=Array.from(t).join(", ");return`${String(e)} → [${s||"∅"}]`})).join("\n")}},_=new Set,E=class{graph;constructor(){this.graph=new A}registerNode(e){this.graph.registerNode(e)}removeNode(e){this.graph.removeNode(e)}addDependency(e,t){this.graph.addDependency(e,t)}removeDependency(e,t){this.graph.removeDependency(e,t)}getDependents(e){return Array.from(this.graph.getDependents(e))}iterDependents(e){return this.graph.iterDependents(e)}getDependencies(e){return Array.from(this.graph.getDependencies(e))}getTransitiveDependents(e){return new Set(Array.from(this.graph.getTransitiveDependents(e,!1)))}setDependencies(e,t){const s=Array.from(t).map((e=>e));this.graph.setDependencies(e,s)}wouldCreateCycle(e,t,s){if(s?.has(t)){const e=Array.from(s),i=e.indexOf(t),r=e.slice(i);return r.push(t),r}const i=this.graph.wouldCreateCycle(e,t);return i||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()}},O=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];var x=class e extends Error{category;constructor(t,s,i){super(t,{cause:i}),this.name="ArtifactError",this.category=s,Object.setPrototypeOf(this,e.prototype)}},C=class extends x{constructor(e){super(`[ArtifactContainer] Artifact "${e}" not found.`,"system"),this.name="ArtifactNotFoundError"}},$=class extends x{constructor(){super("Build superseded by invalidation","system"),this.name="SupersededBuildError"}},D=class extends x{constructor(e){super(e,"system"),this.name="InvalidImportError"}},R=class extends x{constructor(e){super(`Artifact "${e}" instance is not JSON-serializable (POJO are required for persistence)`,"system"),this.name="InvalidExportOperationError"}},N=(new AbortController).signal,P=class{constructor(e,t,s,i,r){this.registry=e,this.cache=t,this.graph=s,this.store=i,this.observer=r}async build(e,t,s){const i=this.cache.get(e);if("singleton"===i?.scope&&i.buildOnce.done())return this.cache.package(e,((t,s)=>this.invalidate(e,t,s)),s);const r=this.registry.getByString(e);if(!r)throw new C(e);const n=t??[];if(n.includes(e))throw new x(`Cycle detected: Artifact "${String(e)}" depends on itself via path: ${[...n,e].join(" -> ")}`,"system");n.push(e);let a=i;a||(a=this.createCachedArtifact(r),this.cache.set(e,a));try{if("transient"===a.scope)return this.executeBuild(r,a,n);const i=a;try{await i.buildOnce.do((()=>this.executeBuild(r,i,n)))}catch(i){if(i instanceof $)return this.build(e,t,s);throw i}return i.stream&&i.streamOnce.do(i.stream),this.cache.package(e,((t,s)=>this.invalidate(e,t,s)),s)}finally{n.pop()}}async executeBuild(e,t,s){const i=e.key,r=String(i),n="transient"===t.scope;t.buildCount++,"singleton"===t.scope&&(t.activeDebounceMs=e.debounce??0);const a={cleanupFunctions:[],disposeFunctions:[],capturedArtifactDeps:new Set,capturedStateSelectors:[],dependencyVersions:new Map},o=this.buildContext(e,t,s,r,a),c=await this.runWithRetries(e,o,a.dependencyVersions);if(this.commitResult(i,t,n,c,a),n){const e=c.ok?c.value:void 0;return{instance:e,error:c.ok?void 0:c.error,ready:c.ok,[i]:e,cleanup:m(a.cleanupFunctions,r),invalidate:async()=>console.warn(`[ArtifactManager] Cannot invalidate transient "${r}"`)}}}buildContext(e,t,s,i,r){const n=e.key,a="transient"===t.scope,{cleanupFunctions:o,disposeFunctions:c,capturedArtifactDeps:h,dependencyVersions:d,capturedStateSelectors:u}=r,l=async(e,t)=>{const r=t?this.computeParamKey(e,t):e;if(r===n)throw new x(`Artifact "${i}" depends on itself.`,"system");const a=this.graph.wouldCreateCycle(n,r);if(a)throw new x(`Adding dependency "${String(r)}" to "${i}" would create a cycle: ${a.join(" -> ")}`,"system");h.add(r);const o=await(t?this.resolveParameterized(e,t):this.build(e,s)),c=this.cache.get(r);return c&&d.set(r,c.version),o},p="singleton"===t.scope?t.controller.signal:N,g=async(e,t)=>{const s=await l(e,t);if(s.error)throw s.error;return s.instance},f=(e,t)=>{const s=function(e,t="."){const s=new Set,i=new Map,r=(e="")=>{if(i.has(e))return i.get(e);const n=new Proxy((()=>{}),{get:(i,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic, arithmetic, or string operations inside a selector.");if(O.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&s.delete(e),s.add(a),r(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions or methods.")}});return i.set(e,n),n};try{e(r())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(s)}(e);return u.push({paths:s,options:t}),e(this.store.get(!0))};return{state:()=>this.store.get(!0),previous:t.instance,signal:p,onCleanup:e=>o.push(e),onDispose:e=>c.push(e),use:e=>e({resolve:l,require:g,select:f}),stream:e=>{if(a)throw new x(`[ArtifactManager] Illegal stream on transient artifact "${i}"`,"system");const s=t,r=async(e,t=void 0)=>{await s.streamSerializer.do((async()=>{void 0!==s.stream&&(s.instance=e,s.error=t,s.version++,this.cache.invalidatePackage(n),await this.processStream(i))}))},o={value:()=>s.instance,get signal(){return s.controller.signal},set:(...e)=>this.store.set(...e),emit:e=>r(e)};s.stream=async()=>{try{const t=await e(o);t&&s.cleanupFunctions.push(t)}catch(e){await r(void 0,e),await this.invalidate(n,!1,!0)}}}}}async runWithRetries(e,t,s){const i=t.signal,r=(e.retries??0)+1;let n=0;for(;n<r;)try{if(i.aborted)throw new $;const a=e.factory(t);let o;if(o=a instanceof Promise?e.timeout?await S(a,e.timeout):await a:a,i.aborted)throw new $;const c=this.detectStaleness(s);if(c){if(n++,s.clear(),n<r)continue;return{ok:!1,error:new x(`Build stale after all retries: dependency "${String(c)}" changed during build.`,"system")}}return{ok:!0,value:o}}catch(e){if(i.aborted||e instanceof $)throw new $;if(e instanceof x)throw e;if(n++,n>=r)return{ok:!1,error:e}}return{ok:!1,error:new Error("Build exhausted retry budget unexpectedly.")}}commitResult(e,t,s,i,r){const{cleanupFunctions:n,disposeFunctions:a,capturedArtifactDeps:o,capturedStateSelectors:c}=r;s||(this.updateDependencyGraph(e,o,c),t.cleanupFunctions=n,t.disposeFunctions=a,t.artifactDependencies=new Set(o),t.stateGroups=c.map((({paths:e,options:t})=>({paths:e,options:t})))),i.ok?(t.instance=i.value,t.error=void 0):(t.instance=void 0,t.error=i.error),t.version++,this.cache.invalidatePackage(e)}detectStaleness(e){for(const[t,s]of e){const e=this.cache.get(t);if(e&&e.version!==s)return t}return null}async invalidate(e,t=!1,s=!1){const i=this.cache.get(e);if(!i)return;if("singleton"!==i.scope)return this.executeInvalidation(e,t,s);const r=i;return r.debounceTimer&&(clearTimeout(r.debounceTimer),r.debounceTimer=void 0),!t&&r.activeDebounceMs>0?new Promise(((i,n)=>{r.debounceTimer=setTimeout((()=>{r.debounceTimer=void 0,this.executeInvalidation(e,t,s).then(i).catch(n)}),r.activeDebounceMs)})):this.executeInvalidation(e,t,s)}async executeInvalidation(e,t,s=!1){const i=this.cache.get(e);i&&"singleton"===i.scope&&await i.invalidationSerializer.do((async()=>{i.version++,await this.cache.invalidateInstance(e),await this.cascadeInvalidation(this.graph.iterDependents(e));const r=this.registry.get(e),n=r&&(t||!r.lazy||this.observer.hasWatchers(e))&&!s;n&&await this.build(e).catch((t=>{t instanceof $||console.error(`[ArtifactManager] Rebuild failed for "${String(e)}":`,t)})),(n||s)&&this.observer.notify(e)}))}async dispose(e){this.cache.get(e)&&(await this.cache.invalidateInstance(e,!0),this.graph.removeNode(e),this.cache.delete(e))}async processStream(e){await this.cascadeInvalidation(this.graph.iterDependents(e)),this.observer.notify(e)}async cascadeInvalidation(e){if(0===e.size)return;const t=[];for(const s of e)t.push(this.invalidate(s).catch((e=>{console.error(`[ArtifactManager] Cascade failed for "${String(s)}":`,e)})));await Promise.all(t)}updateDependencyGraph(e,t,s){const i=this.cache.get(e);if(!i||"singleton"!==i.scope)return;this.graph.registerNode(e),this.graph.setDependencies(e,t),i.stateDependencies=new Set;for(const{paths:e}of s)for(const t of e)i.stateDependencies.add(t);if(i.stateUnsubscribe&&(i.stateUnsubscribe(),i.stateUnsubscribe=void 0),0===s.length)return;const r=()=>this.invalidate(e),n=new Map;for(const{paths:e,options:t}of s){const s=void 0===t?"undefined":JSON.stringify(t);let i=n.get(s);i||(i={options:t,paths:new Set},n.set(s,i));for(const t of e)i.paths.add(t)}const a=[];for(const{options:e,paths:t}of n.values()){if(0===t.size)continue;const s=Array.from(t);void 0===e?a.push(this.store.watch(s,r)):a.push(this.store.watch(s,r,e))}0===a.length?i.stateUnsubscribe=void 0:1===a.length?i.stateUnsubscribe=a[0]:i.stateUnsubscribe=()=>{for(const e of a)e()}}createCachedArtifact(e){return"transient"===e.scope?{scope:"transient",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0}:{scope:"singleton",instance:void 0,error:void 0,version:0,cleanupFunctions:[],disposeFunctions:[],buildCount:0,stateDependencies:new Set,activeDebounceMs:e.debounce?e.debounce:0,controller:new AbortController,buildOnce:new p({retry:!0,throws:!0}),streamOnce:new p({retry:!0,throws:!0}),streamSerializer:new g({yieldMode:"microtask"}),invalidationSerializer:new g({yieldMode:"macrotask"}),stateGroups:[],artifactDependencies:new Set}}resolveStatic(e){if(!this.registry.has(e))throw new C(e);return this.build(e)}async resolveParameterized(e,t){if(!this.registry.has(e))throw new C(String(e));const s=this.registry.get(e);if(!s.paramKey)throw new x(`Artifact "${String(e)}" is not parameterized.`,"external");const i=s.paramKey(t),r=this.registry.getByString(i);if(r&&!r.paramKey&&!r.virtual)throw new x(`Parameterized artifact "${String(e)}" with params ${JSON.stringify(t)} resolves to key "${i}" which is already registered as a static artifact.`,"system");return this.registry.hasString(i)||this.registry.setVirtual(i,{key:i,factory:e=>s.factory({...e,params:t}),scope:s.scope,lazy:s.lazy,timeout:s.timeout,retries:s.retries,debounce:s.debounce,virtual:!0}),this.build(i,void 0,e)}computeParamKey(e,t){const s=this.registry.get(e);if(!s.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);return s.paramKey(t)}},M=class{constructor(e,t,s){this.registry=e,this.cache=t,this.container=s}listeners=new Map;watchers=new Map;watch(e,t=6e4){return this.watchForKey(e,this.registry.get(e),t)}watchParameterized(e,t,s=6e4){const i=this.registry.get(e);if(!i.paramKey)throw new Error(`Artifact "${String(e)}" is not parameterized.`);const r=i.paramKey(t);return this.watchForKey(r,i,s,t)}watchForKey(e,t,s,i){const r="transient"===t.scope,n=r?v(e):e,a=this.watchers.get(n);if(a)return a.observer;const o=new y((async()=>{!r&&void 0===i||this.registry.hasString(e)||this.registry.setVirtual(e,{key:e,factory:r?t.factory:e=>t.factory({...e,params:i}),scope:r?"singleton":t.scope,lazy:t.lazy,timeout:t.timeout,retries:t.retries,debounce:t.debounce,paramKey:t.paramKey,virtual:!0})}),(async()=>{r||void 0!==i?(await this.registry.unregister(n).catch((()=>{})),this.cache.delete(n),this.watchers.delete(n)):this.cache.invalidatePackage(n),this.listeners.delete(n)}),{gracePeriod:r&&void 0===i?"sync":s});let c;const h={id:n,get count(){return o.subscribers},get:(t=!1)=>0!==o.subscribers||t?this.cache.package(n,((e,t)=>this.container.invalidate(n,e,t)),e):b,resolve:()=>c||(c=(async()=>{await o.acquire();try{return await this.container.resolve(n)}finally{o.release(),c=void 0}})(),c),subscribe:(e,t=!0)=>{const s=()=>e(h.get());return o.acquire().then((()=>{this.container.resolve(n).then((()=>{this.listeners.has(n)||this.listeners.set(n,new Set),t&&s(),this.listeners.get(n).add(s)}))})).catch((e=>{console.error(`[ArtifactObserver] Resolution failed for "${n}":`,e),this.listeners.get(n)?.add(s)})),()=>{this.listeners.get(n)?.delete(s),o.release()}}};return this.watchers.set(n,{resource:o,observer:h}),h}evictWatcher(e){[e,v(e)].forEach((e=>{const t=this.watchers.get(e);t&&(t.resource.forceCleanup(),this.watchers.delete(e))}))}notify(e){const t=this.listeners.get(e);if(t&&0!==t.size)for(const s of t)try{s()}catch(t){console.error(`[ArtifactObserver] Listener error for "${e}":`,t)}}hasWatchers(e){return this.watchers.has(e)||this.watchers.has(v(e))}getWatcherCount(e){const t=this.watchers.get(e)||this.watchers.get(v(e));return t?.resource.subscribers??0}clear(){this.watchers.clear(),this.listeners.clear()}},T=class{artifacts=new Map;register({key:e,factory:t,lazy:s,...i}){const{scope:r,...n}=i,a={key:e,factory:t,scope:i.scope??"singleton",lazy:void 0===s||s,...n};return this.artifacts.set(e,a),()=>this.unregister(e)}setVirtual(e,t){this.artifacts.set(e,t)}get(e){if(!this.has(e))throw new C(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()}},L=class e{registry;cache;graph;manager;observer;store;constructor(e){this.store={watch:(...t)=>e.watch(...t),get:()=>e.get(!0),set:(...t)=>e.set(...t),subset:(...t)=>e.subset(...t)},this.registry=new T,this.cache=new I,this.graph=new E,this.observer=new M(this.registry,this.cache,this),this.manager=new P(this.registry,this.cache,this.graph,this.store,this.observer)}debugInfo(){const e=[];return this.registry.keys().forEach((t=>{const s=t,i=this.registry.get(s),r=this.cache.get(s);if(!i)return;let n="idle";r&&("singleton"===r.scope&&void 0!==r.debounceTimer?n="debouncing":"singleton"===r.scope&&r.buildOnce.running()?n="building":r.error?n="error":void 0!==r.instance&&(n="active")),e.push({id:s,scope:i.scope??"singleton",status:n,dependencies:this.graph.getDependencies(s).map((e=>String(e))),dependents:this.graph.getDependents(s).map((e=>String(e))),stateDependencies:"singleton"===r?.scope?Array.from(r.stateDependencies):[],buildCount:r?.buildCount??0})})),e}register(e){const{key:t}=e,s=t;this.registry.has(t)&&(console.warn(`[ArtifactContainer] Overwriting "${s}".`),this.manager.dispose(t).catch((e=>{console.error(`[ArtifactContainer] Failed to dispose existing artifact "${s}":`,e)}))),this.registry.register(e),this.graph.registerNode(t);const i=e.scope??"singleton";return(e.lazy??!0)||"singleton"!==i||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${s}":`,e)})),()=>this.unregister(t)}has(e){return this.registry.has(e)}async unregister(e,t){const s=void 0!==t?this.manager.computeParamKey(e,t):e;await this.manager.dispose(s),await this.registry.unregister(s),this.observer.evictWatcher(s)}async resolve(e,t){return void 0===t?this.manager.resolveStatic(e):this.manager.resolveParameterized(e,t)}async require(e,t){const s=await this.resolve(e,t);if(s.error)throw s.error;return s.instance}watch(e,t,s){return void 0===t?this.observer.watch(e,s):this.observer.watchParameterized(e,t,s)}peek(e,t){const s=void 0!==t?this.manager.computeParamKey(e,t):e;return this.cache.get(s)?.instance}async invalidate(e,t){const s=t?.params,i=t?.replace??!1,r=void 0!==s?this.manager.computeParamKey(e,s):e;return this.manager.invalidate(r,i)}notifyObservers(e){this.observer.notify(e)}hasWatchers(e){return this.observer.hasWatchers(e)}async dispose(){const e=this.registry.keys();await Promise.allSettled(e.map((e=>this.manager.dispose(e).catch((t=>{console.error(`[ArtifactContainer] Failed to dispose artifact "${String(e)}":`,t)}))))),this.registry.clear(),this.cache.clear(),this.graph.clear(),this.observer.clear()}async export(){const e=[];for(const t of this.cache.keys()){const s=this.cache.get(t);if(!s||"singleton"!==s.scope)continue;if(void 0===s.instance)continue;const i=new Set;for(const e of s.stateGroups)for(const t of e.paths)i.add(t);const r=Array.from(i).sort(),n=this.store.subset(r),a=await k(JSON.stringify(n,Object.keys(n).sort()));let o;try{o=structuredClone(s.instance)}catch(e){throw new R(t)}e.push({key:t,instance:o,state:{groups:s.stateGroups.map((e=>({paths:e.paths,options:e.options}))),hash:a},dependencies:Array.from(s.artifactDependencies)})}const t={...{version:"1.0",timestamp:Date.now(),artifacts:e}},s=JSON.stringify(t),i=await k(s);return{...t,checksum:i}}async restore(e){const{checksum:t,...s}=e;if(await k(JSON.stringify(s))!==t)throw new D("Bundle checksum mismatch – data corrupted");if("1.0"!==e.version)throw new D(`Unsupported bundle version: ${e.version}`);const i=new Map;for(const t of e.artifacts)i.set(t.key,t);const r=new Set,n=new Map;for(const t of e.artifacts)for(const e of t.dependencies)n.has(e)||n.set(e,new Set),n.get(e).add(t.key);const a=async e=>{const t=new Set;for(const s of e.state.groups)for(const e of s.paths)t.add(e);const s=Array.from(t).sort(),i=this.store.subset(s);return k(JSON.stringify(i,Object.keys(i).sort()))};for(const t of e.artifacts){await a(t)!==t.state.hash&&r.add(t.key)}const o=Array.from(r);for(;o.length;){const e=o.shift(),t=n.get(e);if(t)for(const e of t)r.has(e)||(r.add(e),o.push(e))}for(const t of e.artifacts){if(r.has(t.key))continue;this.cache.get(t.key)&&await this.cache.invalidateInstance(t.key,!1);const 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 p({retry:!0,throws:!0}),streamSerializer:new g({yieldMode:"microtask"}),invalidationSerializer:new g({yieldMode:"macrotask"}),stateUnsubscribe:void 0,debounceTimer:void 0,controller:new AbortController,streamOnce:new p({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);const s=[];for(const e of t.state.groups){const i=this.store.watch(e.paths,(()=>this.invalidate(t.key)),e.options);s.push(i)}e.stateUnsubscribe=()=>{for(const e of s)e()},this.graph.setDependencies(t.key,t.dependencies)}}static async from(t){const s=new e(t.store);if(t.bundle){if("object"!=typeof t.bundle||!t.bundle.version||!Array.isArray(t.bundle.artifacts))throw new D("Invalid bundle: missing version or artifacts array");await s.restore(t.bundle)}for(const e of t.templates)s.register(e);return s}};function F(e){return"object"==typeof e&&null!==e&&"pause"in e}var K="__pipeline_data__";var z={info:()=>{},error:()=>{}},B=class{constructor(e,t,s,i,r,n,a,o,c,h,d,u,l,p){this.pipeline=t,this.entry=s,this.store=i,this.container=r,this.keyPrefix=n,this.bus=a,this.parentPath=o,this.controller=c,this.once=h,this.logger=d,this.definitionId=u,this.index=l,this.factory=p,this.id=e,this.__registryContainer=r,this.__registryPipelineId=u}id;__registryContainer;__registryPipelineId;on(e,t){return this.bus.on(e,t)}abort(){this.controller.abort()}async run(){const e=await this.once.do((()=>this.execute()));return void 0!==e.error?c(new r({code:s.INTERNAL_ERROR.code,message:`Unexpected throw escaped run(): ${Y(e.error)}`,operation:`pipeline:${this.pipeline.id}`,cause:e.error})):e.value}async execute(){this.bus.emit("pipeline:start",{path:this.parentPath,pipelineId:this.pipeline.id,pipelineLabel:this.pipeline.label,runId:this.id}),this.logger.info(`Pipeline start: ${this.pipeline.id} [${this.id}]`);const e=this.resolveEntryStage();if(!e.ok)return this.failPipeline(e.error);const{stageMap:t,orderedStages:i,stageOrderIndex:n}=this.index;let a=e.value,c=!0;for(;;){if(this.controller.signal.aborted){const e=new r({code:s.OPERATION_ABORTED.code,message:`Run aborted before stage "${a.label}".`,operation:`stage:${a.id}`});return this.failPipeline(e)}const e=c?this.entry:void 0;c=!1;const h=await this.executeStage(a,e);if(!h.ok)return this.failPipeline(h.error);if(this.controller.signal.aborted){const e=new r({code:s.OPERATION_ABORTED.code,message:`Run aborted after stage "${a.label}".`,operation:`stage:${a.id}`});return this.failPipeline(e)}const d=h.value,u="pause"===d.kind?void 0:d.nextInstruction,l=n.get(a.id)??-1,p=void 0!==i[l+1],g="pause"===d.kind?"pause":null===u?"terminate":"string"==typeof u?"jump":p?"advance":"natural-end";if(this.bus.emit("router:evaluated",{path:this.parentPath,stageId:a.id,stageLabel:a.label,runId:this.id,instruction:u,interpretation:g}),"pause"===d.kind){const{checkpoint:e,pauseTimeout:t}=d,s=this.store.get(!0);return this.logger.info(`Pipeline paused: ${this.pipeline.id} [${this.id}] at stage "${e.pausedAtStageId}"`+(void 0!==t?` (timeout: ${t}ms)`:"")),this.bus.emit("pipeline:paused",{path:this.parentPath,pipelineId:this.pipeline.id,pipelineLabel:this.pipeline.label,runId:this.id,checkpoint:e,finalState:s,pauseTimeout:t}),o({status:"paused",runId:this.id,finalState:s,checkpoint:e})}if(null===u)break;if("string"==typeof u){const e=t.get(u);if(!e){const e=new r({code:s.INVALID_COMMAND.code,message:`Router on stage "${a.label}" returned unknown stageId: "${u}"`,operation:`stage:${a.id}`});return this.failPipeline(e)}a=e;continue}const f=i[l+1];if(!f)break;a=f}const h=this.store.get(!0);return this.logger.info(`Pipeline succeeded: ${this.pipeline.id} [${this.id}]`),this.bus.emit("pipeline:success",{path:this.parentPath,pipelineId:this.pipeline.id,pipelineLabel:this.pipeline.label,runId:this.id,finalState:h}),o({status:"succeeded",runId:this.id,finalState:h})}resolveEntryStage(){const{stageMap:e,orderedStages:t}=this.index;if(this.entry?.stage){const t=e.get(this.entry.stage);return t?o(t):c(new r({code:s.INVALID_COMMAND.code,message:`Entry stage "${this.entry.stage}" not found.`,operation:`pipeline:${this.pipeline.id}`}))}const i=t[0];return i?o(i):c(new r({code:s.INVALID_COMMAND.code,message:"Pipeline has no stages.",operation:`pipeline:${this.pipeline.id}`}))}async executeStage(e,t){const s=e.pipelines&&e.pipelines.length>0?"pipelines":"steps",i=[...this.parentPath,{kind:"stage",id:e.id,label:e.label}];this.bus.emit("stage:start",{path:this.parentPath,stageId:e.id,stageLabel:e.label,runId:this.id,mode:s});const r="pipelines"===s?await this.executePipelinesStage(e,i,t):await this.executeStepsStage(e,i,t);return r.ok?"pause"===r.value.kind?this.bus.emit("stage:paused",{path:this.parentPath,stageId:e.id,stageLabel:e.label,runId:this.id,checkpoint:r.value.checkpoint}):this.bus.emit("stage:success",{path:this.parentPath,stageId:e.id,stageLabel:e.label,runId:this.id,nextInstruction:r.value.nextInstruction}):this.bus.emit("stage:failure",{path:this.parentPath,stageId:e.id,stageLabel:e.label,runId:this.id,error:r.error}),r}async executeStepsStage(e,t,i){const n=Object.values(e.steps??{});if(0===n.length){this.logger.info(`Stage "${e.label}" has no steps — skipping.`);const t=q(e.router,this.store.get(!0),{});return o(W(t))}if(this.controller.signal.aborted)return c(new r({code:s.OPERATION_ABORTED.code,message:`Aborted before resolving steps in stage "${e.label}".`,operation:`stage:${e.id}`}));const a=void 0!==i?.step?n.filter((e=>e.id===i.step)):n;if(void 0!==i?.step&&0===a.length)return c(new r({code:s.INVALID_COMMAND.code,message:`Entry step "${i.step}" not found in stage "${e.label}".`,operation:`stage:${e.id}`}));for(const e of a)this.bus.emit("step:start",{path:t,stepId:e.id,stepLabel:e.label,runId:this.id});const h=await Promise.all(a.map((async t=>({step:t,result:await this.container.resolve(V(this.keyPrefix,e.id,t.id))})))),d={};for(const{step:e,result:i}of h)i.ready?(this.bus.emit("step:success",{path:t,stepId:e.id,stepLabel:e.label,runId:this.id}),d[e.id]=o(i.instance)):(this.bus.emit("step:failure",{path:t,stepId:e.id,stepLabel:e.label,runId:this.id,error:i.error}),d[e.id]=c(new r({code:s.BACKEND_ERROR.code,message:Y(i.error)})));const u=h.find((({result:e})=>!e.ready));if(u){const e=u.result.error;return c(new r({code:s.BACKEND_ERROR.code,message:`Step "${u.step.label}" failed: ${Y(e)}`,operation:`step:${u.step.id}`,cause:e}))}const l=h.map((({result:e})=>e.instance)).filter((e=>null!=e));let p;try{await this.store.transaction((async()=>{for(const e of l)await this.store.set(e);const t=q(e.router,this.store.get(!0),d);if(F(t)){const s={runId:this.id,pipelineId:this.definitionId,resumeAt:{stage:t.pause},pausedAtStageId:e.id,pausedAtStageLabel:e.label,pausedOn:(new Date).toISOString()};await G(this.store,s),p={kind:"pause",checkpoint:s,pauseTimeout:t.timeout}}else p=W(t)}),{flush:!0})}catch(t){return c(new r({code:s.CONCURRENCY_ERROR.code,message:`Transaction failed during stage "${e.label}": ${Y(t)}`,operation:`stage:${e.id}`,cause:t}))}return o(p)}async executePipelinesStage(e,t,i){const n=e.pipelines,a=void 0!==i?.pipeline?(()=>{const{index:e}=i.pipeline,t=n[e];return t?[{subPipeline:t,originalIndex:e}]:[]})():n.map(((e,t)=>({subPipeline:e,originalIndex:t})));if(void 0!==i?.pipeline&&0===a.length)return c(new r({code:s.INVALID_COMMAND.code,message:`Entry sub‑pipeline index ${i.pipeline.index} out of bounds.`,operation:`stage:${e.id}`}));this.bus.emit("subpipeline:fork",{path:t,stageId:e.id,stageLabel:e.label,runId:this.id,subPipelineIds:a.map((({subPipeline:e})=>e.id))});const h=await Promise.all(a.map((async({subPipeline:s,originalIndex:r})=>{const n=void 0!==i?.pipeline?{stage:i.pipeline.stage,step:i.pipeline.step}:void 0,a=function(e,t,s){const i=`${t}:pipeline-${s}`;return e?`${e}:${i}`:i}(this.keyPrefix,e.id,r);return{subPipeline:s,originalIndex:r,ctx:await this.factory.buildRunContext(this.id,s,n,this.store,this.bus,t,this.container,a)}}))),d=()=>{h.forEach((({ctx:e})=>e.abort()))};this.controller.signal.addEventListener("abort",d,{once:!0});try{if(this.controller.signal.aborted)return d(),c(new r({code:s.OPERATION_ABORTED.code,message:this.controller.signal.reason,operation:`stage:${e.id}`}));const i=await Promise.all(h.map((({ctx:e})=>e.run()))),n={};for(let e=0;e<a.length;e++)n[a[e].subPipeline.id]=i[e];this.bus.emit("subpipeline:join",{path:t,stageId:e.id,stageLabel:e.label,runId:this.id,results:n});const u=i.findIndex((e=>!e.ok||"failed"===e.value.status));if(-1!==u){const t=a[u].subPipeline.id,n=i[u],o=n.ok?n.value.error:n.error;return c(new r({code:s.BACKEND_ERROR.code,message:`Sub‑pipeline "${t}" failed: ${Y(o)}`,operation:`stage:${e.id}`,cause:o}))}const l=i.findIndex((e=>e.ok&&"paused"===e.value.status));if(-1!==l){const t=i[l].value,{checkpoint:n}=t,h={runId:this.id,pipelineId:this.definitionId,resumeAt:{stage:e.id,pipeline:{index:a[l].originalIndex,stage:n.resumeAt.stage,step:n.resumeAt.step}},pausedAtStageId:e.id,pausedAtStageLabel:e.label,pausedOn:(new Date).toISOString()};try{await this.store.transaction((async()=>{await G(this.store,h)}),{flush:!0})}catch(t){return c(new r({code:s.CONCURRENCY_ERROR.code,message:`Failed to write parent pause checkpoint for stage "${e.label}".`,operation:`stage:${e.id}`,cause:t}))}return o({kind:"pause",checkpoint:h,pauseTimeout:void 0})}let p;try{await this.store.transaction((async()=>{const t=q(e.pipelinesRouter,this.store.get(!0),n);if(F(t)){const s={runId:this.id,pipelineId:this.definitionId,resumeAt:{stage:t.pause},pausedAtStageId:e.id,pausedAtStageLabel:e.label,pausedOn:(new Date).toISOString()};await G(this.store,s),p={kind:"pause",checkpoint:s,pauseTimeout:t.timeout}}else p=W(t)}),{flush:!0})}catch(t){return c(new r({code:s.CONCURRENCY_ERROR.code,message:`Transaction failed evaluating router for stage "${e.label}": ${Y(t)}`,operation:`stage:${e.id}`,cause:t}))}return o(p)}finally{this.controller.signal.removeEventListener("abort",d)}}failPipeline(e){return this.bus.emit("pipeline:failure",{path:this.parentPath,pipelineId:this.pipeline.id,pipelineLabel:this.pipeline.label,runId:this.id,error:e}),c(e)}};function U(e){const t=[...e.stages].sort(((e,t)=>e.order-t.order)),s=new Map,i=new Map;for(let e=0;e<t.length;e++){const r=t[e];s.set(r.id,r),i.set(r.id,e)}return{stageMap:s,orderedStages:t,stageOrderIndex:i}}function j(e,t,s){const i=[];for(const r of e.stages)if(r.steps)for(const e of Object.values(r.steps)){const n={runId:s.runId,pipelineId:s.pipelineId,stageId:r.id,stepId:e.id,signal:s.signal};i.push({key:V(t,r.id,e.id),factory:t=>e.action(t,n),scope:e.scope,...void 0!==e.timeout&&{timeout:e.timeout},...void 0!==e.retries&&{retries:e.retries}})}return i}function V(e,t,s){return e?`${e}:${t}:${s}`:`${t}:${s}`}function q(e,t,s){return e?e(t,s):void 0}function W(e){return{kind:"advance",nextInstruction:e}}function Y(e){return e instanceof Error?e.message:String(e)}async function G(e,t){const s=e,i=t.pipelineId,r=t.runId,n=s.get(!0)[K]??{},a={...n,[i]:{...n[i]??{},[r]:t}};await s.set({[K]:a})}function J(e,t,s){const i=e.get(!0)[K];if(t)return i?.[t]?.[s]??null;if(i)for(const e in i){const t=i[e][s];if(t)return t}return null}exports.PIPELINE_DATA_KEY=K,exports.Pipeline=class{steps=new Map;globalBus=e.createEventBus();serializer=new g;executions=new Map;constructor(e){e&&e.forEach(((e,t)=>{(Array.isArray(e)?e:[e]).forEach((e=>this.steps.set(e.key,{...e,order:t})))}))}getSteps(){return this.steps}step(e){return this.steps.set(e.key,e),this}on(e,t){return this.globalBus.subscribe(e,t)}prepare(e,t,s,i){return new f(this,e,t,s?.signal,i)}async execute(e,t,s){const i=s?.disableDeduplication?`${e}:${Date.now()}:${Math.random()}`:this.getDedupeKey(e,t);let r=this.executions.get(i);r||(r=new p({retry:!0,throws:!1}),this.executions.set(i,r));const n=await r.do((async()=>{const i=await this.serializer.do((async()=>{const i=this.prepare(e,t,{signal:s?.signal},this.globalBus);return await i.run()}));if(i.error)throw i.error;return i.value})).finally((()=>{setTimeout((()=>this.executions.delete(i)),0)}));return n.error?c(n.error):n.value}getRegisteredSteps(){return Array.from(this.steps.keys())}validate(){const e=[];return 0===this.steps.size&&e.push("Pipeline has no registered steps"),e}destroy(){this.steps.clear(),this.globalBus.clear(),this.executions.clear()}groupByOrder(){const e=new Map;for(const t of this.steps.values()){const s=e.get(t.order)??[];s.push(t),e.set(t.order,s)}return e}getDedupeKey(e,t){try{return`${e}:${JSON.stringify(this.sortObjectKeys(t))}`}catch{return`${e}:${Date.now()}:${Math.random()}`}}sortObjectKeys(e){if(null===e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map((e=>this.sortObjectKeys(e)));const t={};return Object.keys(e).sort().forEach((s=>{t[s]=this.sortObjectKeys(e[s])})),t}},exports.PipelineFactory=class{constructor(e,t){this.definition=e,this.logger=t.logger??z,this.storeFactory=t.storeFactory,this.initialStateFactory=t.initialStateFactory,this.registry=t.registry,this.index=U(e)}logger;storeFactory;initialStateFactory;registry;index;async prepare(e,s){const i=s??t.v7(),r=await this.storeFactory(i);await r.ready();const n=this.initialStateFactory?.()??{};await r.set(n),this.logger.info(`Prepared new run "${i}" for pipeline "${this.definition.id}"`);const a=await this.buildRunContext(i,this.definition,e,r,void 0,[]);return this.registry?.register(a,r),a}async resume(e){const t=this.registry?.getLiveContext(e)??null;if(null!==t)return this.logger.info(`Resuming pipeline "${this.definition.id}" [${e}] from live registry context`),o(t);const i=await this.storeFactory(e),n=J(i,void 0,e);if(!n)return c(new r({code:s.NOT_FOUND.code,message:`No checkpoint found for runId "${e}".`,operation:"resume"}));if(n.pipelineId!==this.definition.id)return c(new r({code:s.INVALID_COMMAND.code,message:`Checkpoint runId "${e}" belongs to pipeline "${n.pipelineId}", not "${this.definition.id}" (mismatch-base).`,operation:"resume"}));this.logger.info(`Resuming pipeline "${this.definition.id}" [${e}] from store checkpoint at stage "${n.pausedAtStageId}"`);const a=await this.buildRunContext(e,this.definition,n.resumeAt,i,void 0,[],void 0,void 0,n.containerBundle);return this.registry?.register(a,i),o(a)}async buildRunContext(t,s,i,r,n,a,o,c,h){const d=void 0===o,u=c??"",l=new AbortController,g={runId:t,pipelineId:s.id,signal:l.signal};let f;h?f=await L.from({store:r,bundle:h,templates:j(s,u,g)}):(f=d?new L(r):o,function(e,t,s,i){for(const r of t.stages)if(r.steps)for(const t of Object.values(r.steps)){const n={runId:i.runId,pipelineId:i.pipelineId,stageId:r.id,stepId:t.id,signal:i.signal};e.register({key:V(s,r.id,t.id),factory:e=>t.action(e,n),scope:t.scope,...void 0!==t.timeout&&{timeout:t.timeout},...void 0!==t.retries&&{retries:t.retries}})}}(f,s,u,g));const y=function(e,t){return{emit(s,i){e.emit({name:s,payload:i}),t?.emit(s,i)},on:(t,s)=>e.subscribe(t,s)}}(e.createEventBus(),n),m=new p({retry:!1,throws:!1}),w=d?this.index:U(s);return new B(t,s,i,r,f,u,y,a,l,m,this.logger,this.definition.id,w,this)}},exports.SequentialExecutionContext=f,exports.clearCheckpoint=async function(e,t,s){const i=e,r=i.get(!0)[K]??{},n={...r[t]??{}};delete n[s];const a={...r,[t]:n};await i.set({[K]:a})},exports.isPauseInstruction=F,exports.readCheckpoint=J,exports.writeCheckpoint=G;
|