@elaraai/e3-core 0.0.1-alpha.2

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.
Files changed (63) hide show
  1. package/LICENSE.md +50 -0
  2. package/README.md +103 -0
  3. package/dist/src/dataflow.d.ts +136 -0
  4. package/dist/src/dataflow.d.ts.map +1 -0
  5. package/dist/src/dataflow.js +562 -0
  6. package/dist/src/dataflow.js.map +1 -0
  7. package/dist/src/errors.d.ts +125 -0
  8. package/dist/src/errors.d.ts.map +1 -0
  9. package/dist/src/errors.js +211 -0
  10. package/dist/src/errors.js.map +1 -0
  11. package/dist/src/executions.d.ts +176 -0
  12. package/dist/src/executions.d.ts.map +1 -0
  13. package/dist/src/executions.js +585 -0
  14. package/dist/src/executions.js.map +1 -0
  15. package/dist/src/formats.d.ts +38 -0
  16. package/dist/src/formats.d.ts.map +1 -0
  17. package/dist/src/formats.js +115 -0
  18. package/dist/src/formats.js.map +1 -0
  19. package/dist/src/gc.d.ts +54 -0
  20. package/dist/src/gc.d.ts.map +1 -0
  21. package/dist/src/gc.js +233 -0
  22. package/dist/src/gc.js.map +1 -0
  23. package/dist/src/index.d.ts +25 -0
  24. package/dist/src/index.d.ts.map +1 -0
  25. package/dist/src/index.js +72 -0
  26. package/dist/src/index.js.map +1 -0
  27. package/dist/src/objects.d.ts +62 -0
  28. package/dist/src/objects.d.ts.map +1 -0
  29. package/dist/src/objects.js +245 -0
  30. package/dist/src/objects.js.map +1 -0
  31. package/dist/src/packages.d.ts +93 -0
  32. package/dist/src/packages.d.ts.map +1 -0
  33. package/dist/src/packages.js +370 -0
  34. package/dist/src/packages.js.map +1 -0
  35. package/dist/src/repository.d.ts +38 -0
  36. package/dist/src/repository.d.ts.map +1 -0
  37. package/dist/src/repository.js +103 -0
  38. package/dist/src/repository.js.map +1 -0
  39. package/dist/src/tasks.d.ts +63 -0
  40. package/dist/src/tasks.d.ts.map +1 -0
  41. package/dist/src/tasks.js +145 -0
  42. package/dist/src/tasks.js.map +1 -0
  43. package/dist/src/test-helpers.d.ts +44 -0
  44. package/dist/src/test-helpers.d.ts.map +1 -0
  45. package/dist/src/test-helpers.js +141 -0
  46. package/dist/src/test-helpers.js.map +1 -0
  47. package/dist/src/trees.d.ts +178 -0
  48. package/dist/src/trees.d.ts.map +1 -0
  49. package/dist/src/trees.js +636 -0
  50. package/dist/src/trees.js.map +1 -0
  51. package/dist/src/workspaceLock.d.ts +67 -0
  52. package/dist/src/workspaceLock.d.ts.map +1 -0
  53. package/dist/src/workspaceLock.js +217 -0
  54. package/dist/src/workspaceLock.js.map +1 -0
  55. package/dist/src/workspaceStatus.d.ts +126 -0
  56. package/dist/src/workspaceStatus.d.ts.map +1 -0
  57. package/dist/src/workspaceStatus.js +352 -0
  58. package/dist/src/workspaceStatus.js.map +1 -0
  59. package/dist/src/workspaces.d.ts +150 -0
  60. package/dist/src/workspaces.d.ts.map +1 -0
  61. package/dist/src/workspaces.js +390 -0
  62. package/dist/src/workspaces.js.map +1 -0
  63. package/package.json +59 -0
@@ -0,0 +1,562 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Dataflow execution for e3 workspaces.
7
+ *
8
+ * Executes tasks in a workspace based on their dependency graph. Tasks are
9
+ * executed in parallel where possible, respecting a concurrency limit.
10
+ *
11
+ * The execution model is event-driven with a work queue:
12
+ * 1. Build dependency graph from tasks (input paths -> task -> output path)
13
+ * 2. Compute reverse dependencies (which tasks depend on each output)
14
+ * 3. Initialize ready queue with tasks whose inputs are all assigned
15
+ * 4. Execute tasks from ready queue, respecting concurrency limit
16
+ * 5. On task completion, queue workspace update then check dependents for readiness
17
+ * 6. On failure, stop launching new tasks but wait for running ones
18
+ *
19
+ * IMPORTANT: Workspace state updates are serialized through an async queue to
20
+ * prevent race conditions when multiple tasks complete concurrently. Each task's
21
+ * output is written to the workspace and dependents are notified only after the
22
+ * write completes, ensuring downstream tasks see consistent state.
23
+ */
24
+ import { decodeBeast2For } from '@elaraai/east';
25
+ import { PackageObjectType, TaskObjectType, WorkspaceStateType, pathToString, } from '@elaraai/e3-types';
26
+ import { objectRead } from './objects.js';
27
+ import { taskExecute, executionGetOutput, inputsHash, } from './executions.js';
28
+ import { workspaceGetDatasetHash, workspaceSetDatasetByHash, } from './trees.js';
29
+ import { E3Error, WorkspaceNotFoundError, WorkspaceNotDeployedError, TaskNotFoundError, DataflowError, DataflowAbortedError, isNotFoundError, } from './errors.js';
30
+ import { acquireWorkspaceLock, } from './workspaceLock.js';
31
+ import * as fs from 'fs/promises';
32
+ import * as path from 'path';
33
+ // =============================================================================
34
+ // Async Mutex for Workspace Updates
35
+ // =============================================================================
36
+ /**
37
+ * Simple async mutex to serialize workspace state updates.
38
+ *
39
+ * When multiple tasks complete concurrently, their workspace writes must be
40
+ * serialized to prevent race conditions (read-modify-write on the workspace
41
+ * root hash). This mutex ensures only one update runs at a time.
42
+ */
43
+ class AsyncMutex {
44
+ queue = [];
45
+ locked = false;
46
+ /**
47
+ * Acquire the mutex, execute the callback, then release.
48
+ * If the mutex is already held, waits until it's available.
49
+ */
50
+ async runExclusive(fn) {
51
+ await this.acquire();
52
+ try {
53
+ return await fn();
54
+ }
55
+ finally {
56
+ this.release();
57
+ }
58
+ }
59
+ acquire() {
60
+ return new Promise((resolve) => {
61
+ if (!this.locked) {
62
+ this.locked = true;
63
+ resolve();
64
+ }
65
+ else {
66
+ this.queue.push(resolve);
67
+ }
68
+ });
69
+ }
70
+ release() {
71
+ const next = this.queue.shift();
72
+ if (next) {
73
+ next();
74
+ }
75
+ else {
76
+ this.locked = false;
77
+ }
78
+ }
79
+ }
80
+ // =============================================================================
81
+ // Workspace State Reader
82
+ // =============================================================================
83
+ /**
84
+ * Read workspace state from file.
85
+ * @throws {WorkspaceNotFoundError} If workspace doesn't exist
86
+ * @throws {WorkspaceNotDeployedError} If workspace has no package deployed
87
+ */
88
+ async function readWorkspaceState(repoPath, ws) {
89
+ const stateFile = path.join(repoPath, 'workspaces', `${ws}.beast2`);
90
+ let data;
91
+ try {
92
+ data = await fs.readFile(stateFile);
93
+ }
94
+ catch (err) {
95
+ if (isNotFoundError(err)) {
96
+ throw new WorkspaceNotFoundError(ws);
97
+ }
98
+ throw err;
99
+ }
100
+ if (data.length === 0) {
101
+ throw new WorkspaceNotDeployedError(ws);
102
+ }
103
+ const decoder = decodeBeast2For(WorkspaceStateType);
104
+ return decoder(data);
105
+ }
106
+ // =============================================================================
107
+ // Dependency Graph Building
108
+ // =============================================================================
109
+ /**
110
+ * Build the dependency graph for a workspace.
111
+ *
112
+ * Returns:
113
+ * - taskNodes: Map of task name -> TaskNode
114
+ * - outputToTask: Map of output path string -> task name
115
+ * - taskDependents: Map of task name -> set of dependent task names
116
+ */
117
+ async function buildDependencyGraph(repoPath, ws) {
118
+ // Read workspace state to get package hash
119
+ const state = await readWorkspaceState(repoPath, ws);
120
+ // Read package object to get tasks map
121
+ const pkgData = await objectRead(repoPath, state.packageHash);
122
+ const pkgDecoder = decodeBeast2For(PackageObjectType);
123
+ const pkgObject = pkgDecoder(Buffer.from(pkgData));
124
+ const taskNodes = new Map();
125
+ const outputToTask = new Map(); // output path -> task name
126
+ // First pass: load all tasks and build output->task map
127
+ const taskDecoder = decodeBeast2For(TaskObjectType);
128
+ for (const [taskName, taskHash] of pkgObject.tasks) {
129
+ const taskData = await objectRead(repoPath, taskHash);
130
+ const task = taskDecoder(Buffer.from(taskData));
131
+ const outputPathStr = pathToString(task.output);
132
+ outputToTask.set(outputPathStr, taskName);
133
+ taskNodes.set(taskName, {
134
+ name: taskName,
135
+ hash: taskHash,
136
+ task,
137
+ inputPaths: task.inputs,
138
+ outputPath: task.output,
139
+ unresolvedCount: 0, // Will be computed below
140
+ });
141
+ }
142
+ // Build reverse dependency map: task -> tasks that depend on it
143
+ const taskDependents = new Map();
144
+ for (const taskName of taskNodes.keys()) {
145
+ taskDependents.set(taskName, new Set());
146
+ }
147
+ // Second pass: compute dependencies and unresolved counts
148
+ for (const [taskName, node] of taskNodes) {
149
+ for (const inputPath of node.inputPaths) {
150
+ const inputPathStr = pathToString(inputPath);
151
+ const producerTask = outputToTask.get(inputPathStr);
152
+ if (producerTask) {
153
+ // This input comes from another task's output.
154
+ // The task cannot run until the producer task completes,
155
+ // regardless of whether the output is currently assigned
156
+ // (it might be stale from a previous run).
157
+ taskDependents.get(producerTask).add(taskName);
158
+ node.unresolvedCount++;
159
+ }
160
+ // If not produced by a task, it's an external input - check if assigned
161
+ else {
162
+ const { refType } = await workspaceGetDatasetHash(repoPath, ws, inputPath);
163
+ if (refType === 'unassigned') {
164
+ // External input that is unassigned - this task can never run
165
+ node.unresolvedCount++;
166
+ }
167
+ }
168
+ }
169
+ }
170
+ return { taskNodes, outputToTask, taskDependents };
171
+ }
172
+ // =============================================================================
173
+ // Dataflow Execution
174
+ // =============================================================================
175
+ /**
176
+ * Execute all tasks in a workspace according to the dependency graph.
177
+ *
178
+ * Tasks are executed in parallel where dependencies allow, respecting
179
+ * the concurrency limit. On failure, no new tasks are launched but
180
+ * running tasks are allowed to complete.
181
+ *
182
+ * Acquires an exclusive lock on the workspace for the duration of execution
183
+ * to prevent concurrent modifications. If options.lock is provided, uses that
184
+ * lock instead (caller is responsible for releasing it).
185
+ *
186
+ * @param repoPath - Path to .e3 repository
187
+ * @param ws - Workspace name
188
+ * @param options - Execution options
189
+ * @returns Result of the dataflow execution
190
+ * @throws {WorkspaceLockError} If workspace is locked by another process
191
+ * @throws {WorkspaceNotFoundError} If workspace doesn't exist
192
+ * @throws {WorkspaceNotDeployedError} If workspace has no package deployed
193
+ * @throws {TaskNotFoundError} If filter specifies a task that doesn't exist
194
+ * @throws {DataflowError} If execution fails for other reasons
195
+ */
196
+ export async function dataflowExecute(repoPath, ws, options = {}) {
197
+ // Acquire lock if not provided externally
198
+ const externalLock = options.lock;
199
+ const lock = externalLock ?? await acquireWorkspaceLock(repoPath, ws);
200
+ try {
201
+ return await dataflowExecuteWithLock(repoPath, ws, options);
202
+ }
203
+ finally {
204
+ // Only release the lock if we acquired it internally
205
+ if (!externalLock) {
206
+ await lock.release();
207
+ }
208
+ }
209
+ }
210
+ /**
211
+ * Start dataflow execution in the background (non-blocking).
212
+ *
213
+ * Returns a promise immediately without awaiting execution. The lock is
214
+ * released automatically when execution completes.
215
+ *
216
+ * @param repoPath - Path to .e3 repository
217
+ * @param ws - Workspace name
218
+ * @param options - Execution options (lock must be provided)
219
+ * @returns Promise that resolves when execution completes
220
+ * @throws {WorkspaceNotFoundError} If workspace doesn't exist
221
+ * @throws {WorkspaceNotDeployedError} If workspace has no package deployed
222
+ * @throws {TaskNotFoundError} If filter specifies a task that doesn't exist
223
+ * @throws {DataflowError} If execution fails for other reasons
224
+ */
225
+ export function dataflowStart(repoPath, ws, options) {
226
+ return dataflowExecuteWithLock(repoPath, ws, options)
227
+ .finally(() => options.lock.release());
228
+ }
229
+ /**
230
+ * Internal: Execute dataflow with lock already held.
231
+ */
232
+ async function dataflowExecuteWithLock(repoPath, ws, options) {
233
+ const startTime = Date.now();
234
+ const concurrency = options.concurrency ?? 4;
235
+ let taskNodes;
236
+ let taskDependents;
237
+ try {
238
+ // Build dependency graph
239
+ const graph = await buildDependencyGraph(repoPath, ws);
240
+ taskNodes = graph.taskNodes;
241
+ taskDependents = graph.taskDependents;
242
+ }
243
+ catch (err) {
244
+ // Re-throw E3Errors as-is
245
+ if (err instanceof E3Error)
246
+ throw err;
247
+ // Wrap unexpected errors
248
+ throw new DataflowError(`Failed to build dependency graph: ${err instanceof Error ? err.message : err}`);
249
+ }
250
+ // Apply filter if specified
251
+ const filteredTaskNames = options.filter
252
+ ? new Set([options.filter])
253
+ : null;
254
+ // Validate filter
255
+ if (filteredTaskNames && options.filter && !taskNodes.has(options.filter)) {
256
+ throw new TaskNotFoundError(options.filter);
257
+ }
258
+ // Track execution state
259
+ const results = [];
260
+ let executed = 0;
261
+ let cached = 0;
262
+ let failed = 0;
263
+ let skipped = 0;
264
+ let hasFailure = false;
265
+ let aborted = false;
266
+ // Check for abort signal
267
+ const checkAborted = () => {
268
+ if (options.signal?.aborted && !aborted) {
269
+ aborted = true;
270
+ }
271
+ return aborted;
272
+ };
273
+ // Mutex to serialize workspace state updates.
274
+ // When multiple tasks complete concurrently, their writes to the workspace
275
+ // must be serialized to prevent lost updates (read-modify-write race).
276
+ const workspaceUpdateMutex = new AsyncMutex();
277
+ // Ready queue: tasks with all dependencies resolved
278
+ const readyQueue = [];
279
+ const completed = new Set();
280
+ const inProgress = new Set();
281
+ // Initialize ready queue with tasks that have no unresolved dependencies
282
+ // and pass the filter (if any)
283
+ for (const [taskName, node] of taskNodes) {
284
+ if (node.unresolvedCount === 0) {
285
+ if (!filteredTaskNames || filteredTaskNames.has(taskName)) {
286
+ readyQueue.push(taskName);
287
+ }
288
+ }
289
+ }
290
+ // Check if the task has a valid cached execution for current inputs
291
+ // Returns the output hash if cached, null if re-execution is needed
292
+ async function getCachedOutput(taskName) {
293
+ const node = taskNodes.get(taskName);
294
+ // Gather current input hashes
295
+ const currentInputHashes = [];
296
+ for (const inputPath of node.inputPaths) {
297
+ const { refType, hash } = await workspaceGetDatasetHash(repoPath, ws, inputPath);
298
+ if (refType !== 'value' || hash === null) {
299
+ // Input not assigned, can't be cached
300
+ return null;
301
+ }
302
+ currentInputHashes.push(hash);
303
+ }
304
+ // Check if there's a cached execution for these inputs
305
+ const inHash = inputsHash(currentInputHashes);
306
+ const cachedOutputHash = await executionGetOutput(repoPath, node.hash, inHash);
307
+ if (cachedOutputHash === null) {
308
+ // No cached execution for current inputs
309
+ return null;
310
+ }
311
+ // Also verify the workspace output matches the cached output
312
+ // (in case the workspace was modified outside of execution)
313
+ const { refType, hash: wsOutputHash } = await workspaceGetDatasetHash(repoPath, ws, node.outputPath);
314
+ if (refType !== 'value' || wsOutputHash !== cachedOutputHash) {
315
+ // Workspace output doesn't match cached output, need to re-execute
316
+ // (or update workspace with cached value)
317
+ return null;
318
+ }
319
+ return cachedOutputHash;
320
+ }
321
+ // Execute a single task (does NOT write to workspace - caller must do that)
322
+ async function executeTask(taskName) {
323
+ const node = taskNodes.get(taskName);
324
+ const taskStartTime = Date.now();
325
+ options.onTaskStart?.(taskName);
326
+ // Gather input hashes
327
+ const inputHashes = [];
328
+ for (const inputPath of node.inputPaths) {
329
+ const { refType, hash } = await workspaceGetDatasetHash(repoPath, ws, inputPath);
330
+ if (refType !== 'value' || hash === null) {
331
+ // Input not available - should not happen if dependency tracking is correct
332
+ return {
333
+ name: taskName,
334
+ cached: false,
335
+ state: 'error',
336
+ error: `Input at ${pathToString(inputPath)} is not assigned (refType: ${refType})`,
337
+ duration: Date.now() - taskStartTime,
338
+ };
339
+ }
340
+ inputHashes.push(hash);
341
+ }
342
+ // Execute the task
343
+ const execOptions = {
344
+ force: options.force,
345
+ signal: options.signal,
346
+ onStdout: options.onStdout ? (data) => options.onStdout(taskName, data) : undefined,
347
+ onStderr: options.onStderr ? (data) => options.onStderr(taskName, data) : undefined,
348
+ };
349
+ const result = await taskExecute(repoPath, node.hash, inputHashes, execOptions);
350
+ // Build task result (NOTE: workspace update happens later, in mutex-protected section)
351
+ const taskResult = {
352
+ name: taskName,
353
+ cached: result.cached,
354
+ state: result.state,
355
+ duration: Date.now() - taskStartTime,
356
+ };
357
+ if (result.state === 'error') {
358
+ taskResult.error = result.error ?? undefined;
359
+ }
360
+ else if (result.state === 'failed') {
361
+ taskResult.exitCode = result.exitCode ?? undefined;
362
+ taskResult.error = result.error ?? undefined;
363
+ }
364
+ // Pass output hash to caller for workspace update (if successful)
365
+ if (result.state === 'success' && result.outputHash) {
366
+ taskResult.outputHash = result.outputHash;
367
+ }
368
+ return taskResult;
369
+ }
370
+ // Process dependents when a task completes
371
+ function notifyDependents(taskName) {
372
+ const dependents = taskDependents.get(taskName) ?? new Set();
373
+ for (const depName of dependents) {
374
+ if (completed.has(depName) || inProgress.has(depName))
375
+ continue;
376
+ // Skip dependents not in the filter
377
+ if (filteredTaskNames && !filteredTaskNames.has(depName))
378
+ continue;
379
+ const depNode = taskNodes.get(depName);
380
+ depNode.unresolvedCount--;
381
+ if (depNode.unresolvedCount === 0 && !readyQueue.includes(depName)) {
382
+ readyQueue.push(depName);
383
+ }
384
+ }
385
+ }
386
+ // Mark dependents as skipped when a task fails
387
+ function skipDependents(taskName) {
388
+ const dependents = taskDependents.get(taskName) ?? new Set();
389
+ for (const depName of dependents) {
390
+ if (completed.has(depName) || inProgress.has(depName))
391
+ continue;
392
+ // Skip dependents not in the filter
393
+ if (filteredTaskNames && !filteredTaskNames.has(depName))
394
+ continue;
395
+ // Recursively skip
396
+ completed.add(depName);
397
+ skipped++;
398
+ results.push({
399
+ name: depName,
400
+ cached: false,
401
+ state: 'skipped',
402
+ duration: 0,
403
+ });
404
+ options.onTaskComplete?.({
405
+ name: depName,
406
+ cached: false,
407
+ state: 'skipped',
408
+ duration: 0,
409
+ });
410
+ skipDependents(depName);
411
+ }
412
+ }
413
+ // Main execution loop using a work-stealing approach
414
+ const runningPromises = new Map();
415
+ async function processQueue() {
416
+ while (true) {
417
+ // Check if we're done
418
+ if (readyQueue.length === 0 && runningPromises.size === 0) {
419
+ break;
420
+ }
421
+ // Launch tasks up to concurrency limit if no failure and not aborted
422
+ while (!hasFailure && !checkAborted() && readyQueue.length > 0 && runningPromises.size < concurrency) {
423
+ const taskName = readyQueue.shift();
424
+ if (completed.has(taskName) || inProgress.has(taskName))
425
+ continue;
426
+ // Check if there's a valid cached execution for current inputs
427
+ const cachedOutputHash = await getCachedOutput(taskName);
428
+ if (cachedOutputHash !== null && !options.force) {
429
+ // Valid cached execution exists for current inputs.
430
+ // No workspace write needed (output already matches), but we still
431
+ // need mutex protection for state updates to prevent races with
432
+ // concurrent task completions.
433
+ await workspaceUpdateMutex.runExclusive(() => {
434
+ completed.add(taskName);
435
+ cached++;
436
+ const result = {
437
+ name: taskName,
438
+ cached: true,
439
+ state: 'success',
440
+ duration: 0,
441
+ };
442
+ results.push(result);
443
+ options.onTaskComplete?.(result);
444
+ notifyDependents(taskName);
445
+ });
446
+ continue;
447
+ }
448
+ inProgress.add(taskName);
449
+ const promise = (async () => {
450
+ try {
451
+ const result = await executeTask(taskName);
452
+ // Use mutex to serialize workspace updates and dependent notifications.
453
+ // This prevents race conditions where two tasks complete simultaneously,
454
+ // both read the same workspace state, and one overwrites the other's changes.
455
+ await workspaceUpdateMutex.runExclusive(async () => {
456
+ // Write output to workspace BEFORE notifying dependents
457
+ if (result.state === 'success' && result.outputHash) {
458
+ const node = taskNodes.get(taskName);
459
+ await workspaceSetDatasetByHash(repoPath, ws, node.outputPath, result.outputHash);
460
+ }
461
+ // Now safe to update execution state and notify dependents
462
+ inProgress.delete(taskName);
463
+ completed.add(taskName);
464
+ results.push(result);
465
+ options.onTaskComplete?.(result);
466
+ if (result.state === 'success') {
467
+ if (result.cached) {
468
+ cached++;
469
+ }
470
+ else {
471
+ executed++;
472
+ }
473
+ notifyDependents(taskName);
474
+ }
475
+ else {
476
+ failed++;
477
+ hasFailure = true;
478
+ skipDependents(taskName);
479
+ }
480
+ });
481
+ }
482
+ finally {
483
+ runningPromises.delete(taskName);
484
+ }
485
+ })();
486
+ runningPromises.set(taskName, promise);
487
+ }
488
+ // Wait for at least one task to complete if we can't launch more
489
+ if (runningPromises.size > 0) {
490
+ await Promise.race(runningPromises.values());
491
+ }
492
+ else if (readyQueue.length === 0) {
493
+ // No running tasks and no ready tasks - we might have unresolvable dependencies
494
+ break;
495
+ }
496
+ }
497
+ }
498
+ await processQueue();
499
+ // Wait for any remaining tasks
500
+ if (runningPromises.size > 0) {
501
+ await Promise.all(runningPromises.values());
502
+ }
503
+ // Check for abort one final time
504
+ checkAborted();
505
+ // If aborted, throw with partial results
506
+ if (aborted) {
507
+ throw new DataflowAbortedError(results);
508
+ }
509
+ return {
510
+ success: !hasFailure,
511
+ executed,
512
+ cached,
513
+ failed,
514
+ skipped,
515
+ tasks: results,
516
+ duration: Date.now() - startTime,
517
+ };
518
+ }
519
+ /**
520
+ * Get the dependency graph for a workspace (for visualization/debugging).
521
+ *
522
+ * @param repoPath - Path to .e3 repository
523
+ * @param ws - Workspace name
524
+ * @returns Graph information
525
+ * @throws {WorkspaceNotFoundError} If workspace doesn't exist
526
+ * @throws {WorkspaceNotDeployedError} If workspace has no package deployed
527
+ * @throws {DataflowError} If graph building fails for other reasons
528
+ */
529
+ export async function dataflowGetGraph(repoPath, ws) {
530
+ let taskNodes;
531
+ let outputToTask;
532
+ try {
533
+ const graph = await buildDependencyGraph(repoPath, ws);
534
+ taskNodes = graph.taskNodes;
535
+ outputToTask = graph.outputToTask;
536
+ }
537
+ catch (err) {
538
+ if (err instanceof E3Error)
539
+ throw err;
540
+ throw new DataflowError(`Failed to build dependency graph: ${err instanceof Error ? err.message : err}`);
541
+ }
542
+ const tasks = [];
543
+ for (const [taskName, node] of taskNodes) {
544
+ const dependsOn = [];
545
+ for (const inputPath of node.inputPaths) {
546
+ const inputPathStr = pathToString(inputPath);
547
+ const producerTask = outputToTask.get(inputPathStr);
548
+ if (producerTask) {
549
+ dependsOn.push(producerTask);
550
+ }
551
+ }
552
+ tasks.push({
553
+ name: taskName,
554
+ hash: node.hash,
555
+ inputs: node.inputPaths.map(pathToString),
556
+ output: pathToString(node.outputPath),
557
+ dependsOn,
558
+ });
559
+ }
560
+ return { tasks };
561
+ }
562
+ //# sourceMappingURL=dataflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataflow.js","sourceRoot":"","sources":["../../src/dataflow.ts"],"names":[],"mappings":"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"}