@elaraai/e3-core 0.0.1-beta.0 → 0.0.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +34 -7
  2. package/dist/src/dataflow.d.ts +41 -1
  3. package/dist/src/dataflow.d.ts.map +1 -1
  4. package/dist/src/dataflow.js +165 -36
  5. package/dist/src/dataflow.js.map +1 -1
  6. package/dist/src/errors.d.ts +39 -1
  7. package/dist/src/errors.d.ts.map +1 -1
  8. package/dist/src/errors.js +34 -1
  9. package/dist/src/errors.js.map +1 -1
  10. package/dist/src/executions.d.ts +14 -1
  11. package/dist/src/executions.d.ts.map +1 -1
  12. package/dist/src/executions.js +60 -10
  13. package/dist/src/executions.js.map +1 -1
  14. package/dist/src/formats.d.ts +1 -1
  15. package/dist/src/formats.js +1 -1
  16. package/dist/src/gc.d.ts +1 -1
  17. package/dist/src/gc.js +3 -2
  18. package/dist/src/gc.js.map +1 -1
  19. package/dist/src/index.d.ts +9 -7
  20. package/dist/src/index.d.ts.map +1 -1
  21. package/dist/src/index.js +10 -6
  22. package/dist/src/index.js.map +1 -1
  23. package/dist/src/objects.d.ts +1 -1
  24. package/dist/src/objects.js +1 -1
  25. package/dist/src/packages.d.ts +9 -1
  26. package/dist/src/packages.d.ts.map +1 -1
  27. package/dist/src/packages.js +16 -1
  28. package/dist/src/packages.js.map +1 -1
  29. package/dist/src/repository.d.ts +1 -1
  30. package/dist/src/repository.js +1 -1
  31. package/dist/src/tasks.d.ts +1 -1
  32. package/dist/src/tasks.js +1 -1
  33. package/dist/src/test-helpers.d.ts +1 -1
  34. package/dist/src/test-helpers.js +1 -1
  35. package/dist/src/trees.d.ts +24 -2
  36. package/dist/src/trees.d.ts.map +1 -1
  37. package/dist/src/trees.js +31 -2
  38. package/dist/src/trees.js.map +1 -1
  39. package/dist/src/workspaceLock.d.ts +67 -0
  40. package/dist/src/workspaceLock.d.ts.map +1 -0
  41. package/dist/src/workspaceLock.js +217 -0
  42. package/dist/src/workspaceLock.js.map +1 -0
  43. package/dist/src/workspaceStatus.d.ts +126 -0
  44. package/dist/src/workspaceStatus.d.ts.map +1 -0
  45. package/dist/src/workspaceStatus.js +352 -0
  46. package/dist/src/workspaceStatus.js.map +1 -0
  47. package/dist/src/workspaces.d.ts +37 -3
  48. package/dist/src/workspaces.d.ts.map +1 -1
  49. package/dist/src/workspaces.js +56 -22
  50. package/dist/src/workspaces.js.map +1 -1
  51. package/package.json +13 -4
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { type LockHolder } from './errors.js';
6
+ /**
7
+ * Status of a dataset in the workspace.
8
+ */
9
+ export type DatasetStatus = {
10
+ type: 'unset';
11
+ } | {
12
+ type: 'stale';
13
+ } | {
14
+ type: 'up-to-date';
15
+ };
16
+ /**
17
+ * Status of a task in the workspace.
18
+ */
19
+ export type TaskStatus = {
20
+ type: 'up-to-date';
21
+ cached: boolean;
22
+ } | {
23
+ type: 'ready';
24
+ } | {
25
+ type: 'waiting';
26
+ reason: string;
27
+ } | {
28
+ type: 'in-progress';
29
+ pid?: number;
30
+ startedAt?: string;
31
+ } | {
32
+ type: 'failed';
33
+ exitCode: number;
34
+ completedAt?: string;
35
+ } | {
36
+ type: 'error';
37
+ message: string;
38
+ completedAt?: string;
39
+ } | {
40
+ type: 'stale-running';
41
+ pid?: number;
42
+ startedAt?: string;
43
+ };
44
+ /**
45
+ * Information about a dataset in the status report.
46
+ */
47
+ export interface DatasetStatusInfo {
48
+ /** Dataset path (e.g., "inputs.sales_data") */
49
+ path: string;
50
+ /** Current status */
51
+ status: DatasetStatus;
52
+ /** Hash of current value (if set) */
53
+ hash: string | null;
54
+ /** True if this is a task output */
55
+ isTaskOutput: boolean;
56
+ /** Name of task that produces this (if any) */
57
+ producedBy: string | null;
58
+ }
59
+ /**
60
+ * Information about a task in the status report.
61
+ */
62
+ export interface TaskStatusInfo {
63
+ /** Task name */
64
+ name: string;
65
+ /** Task hash */
66
+ hash: string;
67
+ /** Current status */
68
+ status: TaskStatus;
69
+ /** Input dataset paths */
70
+ inputs: string[];
71
+ /** Output dataset path */
72
+ output: string;
73
+ /** Tasks this one depends on */
74
+ dependsOn: string[];
75
+ }
76
+ /**
77
+ * Complete workspace status report.
78
+ */
79
+ export interface WorkspaceStatusResult {
80
+ /** Workspace name */
81
+ workspace: string;
82
+ /** Lock status - null if not locked */
83
+ lock: LockHolder | null;
84
+ /** Status of all datasets */
85
+ datasets: DatasetStatusInfo[];
86
+ /** Status of all tasks */
87
+ tasks: TaskStatusInfo[];
88
+ /** Summary counts */
89
+ summary: {
90
+ datasets: {
91
+ total: number;
92
+ unset: number;
93
+ stale: number;
94
+ upToDate: number;
95
+ };
96
+ tasks: {
97
+ total: number;
98
+ upToDate: number;
99
+ ready: number;
100
+ waiting: number;
101
+ inProgress: number;
102
+ failed: number;
103
+ error: number;
104
+ staleRunning: number;
105
+ };
106
+ };
107
+ }
108
+ /**
109
+ * Get comprehensive status of a workspace.
110
+ *
111
+ * Performs a dry-run analysis of the workspace to determine:
112
+ * - Whether the workspace is locked (and by whom)
113
+ * - Status of each dataset (unset, stale, up-to-date)
114
+ * - Status of each task (up-to-date, ready, waiting, in-progress)
115
+ *
116
+ * This is a read-only operation that does not modify workspace state
117
+ * and does not require acquiring a lock.
118
+ *
119
+ * @param repoPath - Path to .e3 repository
120
+ * @param ws - Workspace name
121
+ * @returns Complete status report
122
+ * @throws {WorkspaceNotFoundError} If workspace doesn't exist
123
+ * @throws {WorkspaceNotDeployedError} If workspace has no package deployed
124
+ */
125
+ export declare function workspaceStatus(repoPath: string, ws: string): Promise<WorkspaceStatusResult>;
126
+ //# sourceMappingURL=workspaceStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceStatus.d.ts","sourceRoot":"","sources":["../../src/workspaceStatus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Workspace status - dry-run analysis of dataflow execution state.
7
+ *
8
+ * Provides a complete view of workspace state including:
9
+ * - Lock status (who holds it, since when)
10
+ * - Dataset status (unset, stale, up-to-date)
11
+ * - Task status (up-to-date, ready, waiting, in-progress)
12
+ *
13
+ * This is read-only and does not require a lock.
14
+ */
15
+ import { decodeBeast2For, variant } from '@elaraai/east';
16
+ import { PackageObjectType, TaskObjectType, WorkspaceStateType, pathToString, } from '@elaraai/e3-types';
17
+ import { objectRead } from './objects.js';
18
+ import { executionGet, inputsHash, } from './executions.js';
19
+ import { workspaceGetDatasetHash } from './trees.js';
20
+ import { WorkspaceNotFoundError, WorkspaceNotDeployedError, isNotFoundError, } from './errors.js';
21
+ import { getWorkspaceLockHolder } from './workspaceLock.js';
22
+ import * as fs from 'fs/promises';
23
+ import * as path from 'path';
24
+ // =============================================================================
25
+ // Workspace State Reader (duplicated to avoid circular deps)
26
+ // =============================================================================
27
+ /**
28
+ * Read workspace state from file.
29
+ */
30
+ async function readWorkspaceState(repoPath, ws) {
31
+ const stateFile = path.join(repoPath, 'workspaces', `${ws}.beast2`);
32
+ let data;
33
+ try {
34
+ data = await fs.readFile(stateFile);
35
+ }
36
+ catch (err) {
37
+ if (isNotFoundError(err)) {
38
+ throw new WorkspaceNotFoundError(ws);
39
+ }
40
+ throw err;
41
+ }
42
+ if (data.length === 0) {
43
+ throw new WorkspaceNotDeployedError(ws);
44
+ }
45
+ const decoder = decodeBeast2For(WorkspaceStateType);
46
+ return decoder(data);
47
+ }
48
+ // =============================================================================
49
+ // Main Function
50
+ // =============================================================================
51
+ /**
52
+ * Get comprehensive status of a workspace.
53
+ *
54
+ * Performs a dry-run analysis of the workspace to determine:
55
+ * - Whether the workspace is locked (and by whom)
56
+ * - Status of each dataset (unset, stale, up-to-date)
57
+ * - Status of each task (up-to-date, ready, waiting, in-progress)
58
+ *
59
+ * This is a read-only operation that does not modify workspace state
60
+ * and does not require acquiring a lock.
61
+ *
62
+ * @param repoPath - Path to .e3 repository
63
+ * @param ws - Workspace name
64
+ * @returns Complete status report
65
+ * @throws {WorkspaceNotFoundError} If workspace doesn't exist
66
+ * @throws {WorkspaceNotDeployedError} If workspace has no package deployed
67
+ */
68
+ export async function workspaceStatus(repoPath, ws) {
69
+ // Check lock status first
70
+ const lock = await getWorkspaceLockHolder(repoPath, ws);
71
+ // Read workspace state
72
+ const state = await readWorkspaceState(repoPath, ws);
73
+ // Read package object to get tasks and structure
74
+ const pkgData = await objectRead(repoPath, state.packageHash);
75
+ const pkgDecoder = decodeBeast2For(PackageObjectType);
76
+ const pkgObject = pkgDecoder(Buffer.from(pkgData));
77
+ // Build task nodes
78
+ const taskNodes = new Map();
79
+ const outputToTask = new Map(); // output path -> task name
80
+ const taskDecoder = decodeBeast2For(TaskObjectType);
81
+ for (const [taskName, taskHash] of pkgObject.tasks) {
82
+ const taskData = await objectRead(repoPath, taskHash);
83
+ const task = taskDecoder(Buffer.from(taskData));
84
+ const outputPathStr = pathToString(task.output);
85
+ outputToTask.set(outputPathStr, taskName);
86
+ taskNodes.set(taskName, {
87
+ name: taskName,
88
+ hash: taskHash,
89
+ task,
90
+ inputPaths: task.inputs,
91
+ outputPath: task.output,
92
+ });
93
+ }
94
+ // Collect all dataset paths from structure
95
+ const datasetPaths = [];
96
+ collectDatasetPaths(pkgObject.data.structure, [], datasetPaths);
97
+ // Determine task dependencies
98
+ const taskDependsOn = new Map();
99
+ for (const [taskName, node] of taskNodes) {
100
+ const deps = [];
101
+ for (const inputPath of node.inputPaths) {
102
+ const inputPathStr = pathToString(inputPath);
103
+ const producerTask = outputToTask.get(inputPathStr);
104
+ if (producerTask) {
105
+ deps.push(producerTask);
106
+ }
107
+ }
108
+ taskDependsOn.set(taskName, deps);
109
+ }
110
+ // Determine which tasks are stale (need to rerun)
111
+ // A task is stale if:
112
+ // 1. No cached execution for current inputs, OR
113
+ // 2. Cached output doesn't match current workspace output, OR
114
+ // 3. Any upstream task is stale
115
+ const taskIsStale = new Map();
116
+ const taskStatus = new Map();
117
+ // First pass: determine which tasks have valid cached executions
118
+ for (const [taskName, node] of taskNodes) {
119
+ const status = await computeTaskStatus(repoPath, ws, node, outputToTask, taskNodes, taskIsStale);
120
+ taskStatus.set(taskName, status);
121
+ taskIsStale.set(taskName, status.type !== 'up-to-date');
122
+ }
123
+ // Second pass: mark tasks as waiting if their upstream is stale
124
+ for (const [taskName] of taskNodes) {
125
+ const currentStatus = taskStatus.get(taskName);
126
+ if (currentStatus.type === 'ready') {
127
+ // Check if any upstream task is stale
128
+ const deps = taskDependsOn.get(taskName) ?? [];
129
+ for (const depName of deps) {
130
+ if (taskIsStale.get(depName)) {
131
+ taskStatus.set(taskName, {
132
+ type: 'waiting',
133
+ reason: `Waiting for task '${depName}'`,
134
+ });
135
+ break;
136
+ }
137
+ }
138
+ }
139
+ }
140
+ // Build dataset status
141
+ const datasetStatusInfos = [];
142
+ for (const datasetPath of datasetPaths) {
143
+ const pathStr = pathToString(datasetPath);
144
+ const { refType, hash } = await workspaceGetDatasetHash(repoPath, ws, datasetPath);
145
+ const producerTask = outputToTask.get(pathStr) ?? null;
146
+ const isTaskOutput = producerTask !== null;
147
+ let status;
148
+ if (refType === 'unassigned') {
149
+ status = { type: 'unset' };
150
+ }
151
+ else if (isTaskOutput && producerTask && taskIsStale.get(producerTask)) {
152
+ status = { type: 'stale' };
153
+ }
154
+ else {
155
+ status = { type: 'up-to-date' };
156
+ }
157
+ datasetStatusInfos.push({
158
+ path: pathStr,
159
+ status,
160
+ hash,
161
+ isTaskOutput,
162
+ producedBy: producerTask,
163
+ });
164
+ }
165
+ // Build task status info
166
+ const taskStatusInfos = [];
167
+ for (const [taskName, node] of taskNodes) {
168
+ taskStatusInfos.push({
169
+ name: taskName,
170
+ hash: node.hash,
171
+ status: taskStatus.get(taskName),
172
+ inputs: node.inputPaths.map(pathToString),
173
+ output: pathToString(node.outputPath),
174
+ dependsOn: taskDependsOn.get(taskName) ?? [],
175
+ });
176
+ }
177
+ // Compute summary
178
+ const summary = {
179
+ datasets: {
180
+ total: datasetStatusInfos.length,
181
+ unset: datasetStatusInfos.filter((d) => d.status.type === 'unset').length,
182
+ stale: datasetStatusInfos.filter((d) => d.status.type === 'stale').length,
183
+ upToDate: datasetStatusInfos.filter((d) => d.status.type === 'up-to-date').length,
184
+ },
185
+ tasks: {
186
+ total: taskStatusInfos.length,
187
+ upToDate: taskStatusInfos.filter((t) => t.status.type === 'up-to-date').length,
188
+ ready: taskStatusInfos.filter((t) => t.status.type === 'ready').length,
189
+ waiting: taskStatusInfos.filter((t) => t.status.type === 'waiting').length,
190
+ inProgress: taskStatusInfos.filter((t) => t.status.type === 'in-progress').length,
191
+ failed: taskStatusInfos.filter((t) => t.status.type === 'failed').length,
192
+ error: taskStatusInfos.filter((t) => t.status.type === 'error').length,
193
+ staleRunning: taskStatusInfos.filter((t) => t.status.type === 'stale-running').length,
194
+ },
195
+ };
196
+ return {
197
+ workspace: ws,
198
+ lock,
199
+ datasets: datasetStatusInfos,
200
+ tasks: taskStatusInfos,
201
+ summary,
202
+ };
203
+ }
204
+ // =============================================================================
205
+ // Helper Functions
206
+ // =============================================================================
207
+ /**
208
+ * Recursively collect all dataset paths from a structure.
209
+ */
210
+ function collectDatasetPaths(structure, currentPath, result) {
211
+ if (structure.type === 'value') {
212
+ result.push(currentPath);
213
+ }
214
+ else if (structure.type === 'struct') {
215
+ for (const [fieldName, childStructure] of structure.value) {
216
+ const childPath = [...currentPath, variant('field', fieldName)];
217
+ collectDatasetPaths(childStructure, childPath, result);
218
+ }
219
+ }
220
+ }
221
+ /**
222
+ * Compute the status of a task.
223
+ */
224
+ async function computeTaskStatus(repoPath, ws, node, outputToTask, _taskNodes, _taskIsStale) {
225
+ // First, check if execution is in progress
226
+ const inProgressStatus = await checkInProgress(repoPath, node.hash);
227
+ if (inProgressStatus) {
228
+ return inProgressStatus;
229
+ }
230
+ // Gather current input hashes
231
+ const currentInputHashes = [];
232
+ let hasUnsetInputs = false;
233
+ let waitingOnTasks = [];
234
+ for (const inputPath of node.inputPaths) {
235
+ const inputPathStr = pathToString(inputPath);
236
+ const { refType, hash } = await workspaceGetDatasetHash(repoPath, ws, inputPath);
237
+ if (refType === 'unassigned' || hash === null) {
238
+ hasUnsetInputs = true;
239
+ // Check if this is produced by another task
240
+ const producerTask = outputToTask.get(inputPathStr);
241
+ if (producerTask) {
242
+ waitingOnTasks.push(producerTask);
243
+ }
244
+ else {
245
+ // External input that is unset
246
+ return {
247
+ type: 'waiting',
248
+ reason: `Input '${inputPathStr}' is not set`,
249
+ };
250
+ }
251
+ }
252
+ else {
253
+ currentInputHashes.push(hash);
254
+ }
255
+ }
256
+ // If any inputs are unset and produced by tasks, we're waiting
257
+ if (hasUnsetInputs && waitingOnTasks.length > 0) {
258
+ return {
259
+ type: 'waiting',
260
+ reason: `Waiting for task(s): ${waitingOnTasks.join(', ')}`,
261
+ };
262
+ }
263
+ // If any inputs are unset (external), we're waiting
264
+ if (hasUnsetInputs) {
265
+ return {
266
+ type: 'waiting',
267
+ reason: 'Some inputs are not set',
268
+ };
269
+ }
270
+ // Check the execution status for these inputs
271
+ const inHash = inputsHash(currentInputHashes);
272
+ const execStatus = await executionGet(repoPath, node.hash, inHash);
273
+ if (execStatus === null) {
274
+ // No execution attempted - task is ready to run
275
+ return { type: 'ready' };
276
+ }
277
+ // Check the execution status type
278
+ switch (execStatus.type) {
279
+ case 'running': {
280
+ // Execution was marked as running - check if process is still alive
281
+ // For now, just report it (process liveness check is done in checkInProgress)
282
+ // If we reach here, checkInProgress didn't find it, so it might be stale
283
+ return {
284
+ type: 'stale-running',
285
+ pid: Number(execStatus.value.pid),
286
+ startedAt: execStatus.value.startedAt.toISOString(),
287
+ };
288
+ }
289
+ case 'failed': {
290
+ // Task ran but returned non-zero exit code
291
+ return {
292
+ type: 'failed',
293
+ exitCode: Number(execStatus.value.exitCode),
294
+ completedAt: execStatus.value.completedAt.toISOString(),
295
+ };
296
+ }
297
+ case 'error': {
298
+ // Internal error during execution
299
+ return {
300
+ type: 'error',
301
+ message: execStatus.value.message,
302
+ completedAt: execStatus.value.completedAt.toISOString(),
303
+ };
304
+ }
305
+ case 'success': {
306
+ // Execution succeeded - check if workspace output matches
307
+ const cachedOutputHash = execStatus.value.outputHash;
308
+ const { refType, hash: wsOutputHash } = await workspaceGetDatasetHash(repoPath, ws, node.outputPath);
309
+ if (refType !== 'value' || wsOutputHash !== cachedOutputHash) {
310
+ // Workspace output doesn't match - task needs to run
311
+ // (This might happen if workspace was modified externally)
312
+ return { type: 'ready' };
313
+ }
314
+ // Everything matches - task is up-to-date
315
+ return { type: 'up-to-date', cached: true };
316
+ }
317
+ default:
318
+ // Unknown status type - treat as ready
319
+ return { type: 'ready' };
320
+ }
321
+ }
322
+ /**
323
+ * Check if an execution is currently in progress for a task.
324
+ *
325
+ * Looks for a 'running' execution status that is still alive.
326
+ */
327
+ async function checkInProgress(repoPath, taskHash) {
328
+ // List all executions for this task
329
+ const execDir = path.join(repoPath, 'executions', taskHash);
330
+ try {
331
+ const entries = await fs.readdir(execDir);
332
+ for (const inHash of entries) {
333
+ if (!/^[a-f0-9]{64}$/.test(inHash))
334
+ continue;
335
+ const status = await executionGet(repoPath, taskHash, inHash);
336
+ if (status?.type === 'running') {
337
+ // Found a running execution
338
+ // We could also verify the process is still alive here
339
+ return {
340
+ type: 'in-progress',
341
+ pid: Number(status.value.pid),
342
+ startedAt: status.value.startedAt.toISOString(),
343
+ };
344
+ }
345
+ }
346
+ }
347
+ catch {
348
+ // No executions directory
349
+ }
350
+ return null;
351
+ }
352
+ //# sourceMappingURL=workspaceStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceStatus.js","sourceRoot":"","sources":["../../src/workspaceStatus.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Copyright (c) 2025 Elara AI Pty Ltd
3
- * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
4
  */
5
5
  import type { WorkspaceState } from '@elaraai/e3-types';
6
+ import { type WorkspaceLockHandle } from './workspaceLock.js';
6
7
  /**
7
8
  * Create an empty workspace.
8
9
  *
@@ -14,16 +15,32 @@ import type { WorkspaceState } from '@elaraai/e3-types';
14
15
  * @throws {WorkspaceExistsError} If workspace already exists
15
16
  */
16
17
  export declare function workspaceCreate(repoPath: string, name: string): Promise<void>;
18
+ /**
19
+ * Options for workspace removal.
20
+ */
21
+ export interface WorkspaceRemoveOptions {
22
+ /**
23
+ * External workspace lock to use. If provided, the caller is responsible
24
+ * for releasing the lock after the operation. If not provided, workspaceRemove
25
+ * will acquire and release a lock internally.
26
+ */
27
+ lock?: WorkspaceLockHandle;
28
+ }
17
29
  /**
18
30
  * Remove a workspace.
19
31
  *
20
32
  * Objects remain until repoGc is run.
21
33
  *
34
+ * Acquires a workspace lock to prevent removing a workspace while a dataflow
35
+ * is running. Throws WorkspaceLockError if the workspace is currently locked.
36
+ *
22
37
  * @param repoPath - Path to .e3 repository
23
38
  * @param name - Workspace name
39
+ * @param options - Optional settings including external lock
24
40
  * @throws {WorkspaceNotFoundError} If workspace doesn't exist
41
+ * @throws {WorkspaceLockError} If workspace is locked by another process
25
42
  */
26
- export declare function workspaceRemove(repoPath: string, name: string): Promise<void>;
43
+ export declare function workspaceRemove(repoPath: string, name: string, options?: WorkspaceRemoveOptions): Promise<void>;
27
44
  /**
28
45
  * List workspace names.
29
46
  *
@@ -73,18 +90,35 @@ export declare function workspaceGetRoot(repoPath: string, name: string): Promis
73
90
  * @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
74
91
  */
75
92
  export declare function workspaceSetRoot(repoPath: string, name: string, hash: string): Promise<void>;
93
+ /**
94
+ * Options for workspace deployment.
95
+ */
96
+ export interface WorkspaceDeployOptions {
97
+ /**
98
+ * External workspace lock to use. If provided, the caller is responsible
99
+ * for releasing the lock after the operation. If not provided, workspaceDeploy
100
+ * will acquire and release a lock internally.
101
+ */
102
+ lock?: WorkspaceLockHandle;
103
+ }
76
104
  /**
77
105
  * Deploy a package to a workspace.
78
106
  *
79
107
  * Creates the workspace if it doesn't exist. Writes state file atomically
80
108
  * containing deployment info and root hash.
81
109
  *
110
+ * Acquires a workspace lock to prevent conflicts with running dataflows
111
+ * or concurrent deploys. Throws WorkspaceLockError if the workspace is
112
+ * currently locked by another process.
113
+ *
82
114
  * @param repoPath - Path to .e3 repository
83
115
  * @param name - Workspace name
84
116
  * @param pkgName - Package name
85
117
  * @param pkgVersion - Package version
118
+ * @param options - Optional settings including external lock
119
+ * @throws {WorkspaceLockError} If workspace is locked by another process
86
120
  */
87
- export declare function workspaceDeploy(repoPath: string, name: string, pkgName: string, pkgVersion: string): Promise<void>;
121
+ export declare function workspaceDeploy(repoPath: string, name: string, pkgName: string, pkgVersion: string, options?: WorkspaceDeployOptions): Promise<void>;
88
122
  /**
89
123
  * Result of exporting a workspace
90
124
  */
@@ -1 +1 @@
1
- {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/workspaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAqFvE;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBnB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAMhC;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAO1D;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,CAAC,CAqGhC"}
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/workspaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AASvE,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AA6EpF;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBnB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAMhC;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAO1D;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,CAAC,CAqGhC"}