@elaraai/e3-core 0.0.2-beta.3 → 0.0.2-beta.30
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 +25 -22
- package/dist/src/dataflow/api-compat.d.ts +90 -0
- package/dist/src/dataflow/api-compat.d.ts.map +1 -0
- package/dist/src/dataflow/api-compat.js +134 -0
- package/dist/src/dataflow/api-compat.js.map +1 -0
- package/dist/src/dataflow/index.d.ts +18 -0
- package/dist/src/dataflow/index.d.ts.map +1 -0
- package/dist/src/dataflow/index.js +23 -0
- package/dist/src/dataflow/index.js.map +1 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.d.ts +53 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.d.ts.map +1 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.js +416 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.js.map +1 -0
- package/dist/src/dataflow/orchestrator/index.d.ts +12 -0
- package/dist/src/dataflow/orchestrator/index.d.ts.map +1 -0
- package/dist/src/dataflow/orchestrator/index.js +12 -0
- package/dist/src/dataflow/orchestrator/index.js.map +1 -0
- package/dist/src/dataflow/orchestrator/interfaces.d.ts +157 -0
- package/dist/src/dataflow/orchestrator/interfaces.d.ts.map +1 -0
- package/dist/src/dataflow/orchestrator/interfaces.js +51 -0
- package/dist/src/dataflow/orchestrator/interfaces.js.map +1 -0
- package/dist/src/dataflow/state-store/FileStateStore.d.ts +67 -0
- package/dist/src/dataflow/state-store/FileStateStore.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/FileStateStore.js +286 -0
- package/dist/src/dataflow/state-store/FileStateStore.js.map +1 -0
- package/dist/src/dataflow/state-store/InMemoryStateStore.d.ts +42 -0
- package/dist/src/dataflow/state-store/InMemoryStateStore.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/InMemoryStateStore.js +214 -0
- package/dist/src/dataflow/state-store/InMemoryStateStore.js.map +1 -0
- package/dist/src/dataflow/state-store/index.d.ts +13 -0
- package/dist/src/dataflow/state-store/index.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/index.js +13 -0
- package/dist/src/dataflow/state-store/index.js.map +1 -0
- package/dist/src/dataflow/state-store/interfaces.d.ts +159 -0
- package/dist/src/dataflow/state-store/interfaces.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/interfaces.js +6 -0
- package/dist/src/dataflow/state-store/interfaces.js.map +1 -0
- package/dist/src/dataflow/steps.d.ts +176 -0
- package/dist/src/dataflow/steps.d.ts.map +1 -0
- package/dist/src/dataflow/steps.js +528 -0
- package/dist/src/dataflow/steps.js.map +1 -0
- package/dist/src/dataflow/types.d.ts +116 -0
- package/dist/src/dataflow/types.d.ts.map +1 -0
- package/dist/src/dataflow/types.js +7 -0
- package/dist/src/dataflow/types.js.map +1 -0
- package/dist/src/dataflow.d.ts +142 -9
- package/dist/src/dataflow.d.ts.map +1 -1
- package/dist/src/dataflow.js +427 -64
- package/dist/src/dataflow.js.map +1 -1
- package/dist/src/errors.d.ts +39 -9
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +51 -8
- package/dist/src/errors.js.map +1 -1
- package/dist/src/execution/LocalTaskRunner.d.ts +73 -0
- package/dist/src/execution/LocalTaskRunner.d.ts.map +1 -0
- package/dist/src/execution/LocalTaskRunner.js +399 -0
- package/dist/src/execution/LocalTaskRunner.js.map +1 -0
- package/dist/src/execution/MockTaskRunner.d.ts +49 -0
- package/dist/src/execution/MockTaskRunner.d.ts.map +1 -0
- package/dist/src/execution/MockTaskRunner.js +55 -0
- package/dist/src/execution/MockTaskRunner.js.map +1 -0
- package/dist/src/execution/index.d.ts +16 -0
- package/dist/src/execution/index.d.ts.map +1 -0
- package/dist/src/execution/index.js +8 -0
- package/dist/src/execution/index.js.map +1 -0
- package/dist/src/execution/interfaces.d.ts +246 -0
- package/dist/src/execution/interfaces.d.ts.map +1 -0
- package/dist/src/execution/interfaces.js +6 -0
- package/dist/src/execution/interfaces.js.map +1 -0
- package/dist/src/execution/processHelpers.d.ts +20 -0
- package/dist/src/execution/processHelpers.d.ts.map +1 -0
- package/dist/src/execution/processHelpers.js +62 -0
- package/dist/src/execution/processHelpers.js.map +1 -0
- package/dist/src/executions.d.ts +71 -104
- package/dist/src/executions.d.ts.map +1 -1
- package/dist/src/executions.js +110 -476
- package/dist/src/executions.js.map +1 -1
- package/dist/src/index.d.ts +17 -9
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +44 -18
- package/dist/src/index.js.map +1 -1
- package/dist/src/objects.d.ts +6 -53
- package/dist/src/objects.d.ts.map +1 -1
- package/dist/src/objects.js +11 -232
- package/dist/src/objects.js.map +1 -1
- package/dist/src/packages.d.ts +22 -14
- package/dist/src/packages.d.ts.map +1 -1
- package/dist/src/packages.js +116 -83
- package/dist/src/packages.js.map +1 -1
- package/dist/src/storage/in-memory/InMemoryRepoStore.d.ts +35 -0
- package/dist/src/storage/in-memory/InMemoryRepoStore.d.ts.map +1 -0
- package/dist/src/storage/in-memory/InMemoryRepoStore.js +107 -0
- package/dist/src/storage/in-memory/InMemoryRepoStore.js.map +1 -0
- package/dist/src/storage/in-memory/InMemoryStorage.d.ts +114 -0
- package/dist/src/storage/in-memory/InMemoryStorage.d.ts.map +1 -0
- package/dist/src/storage/in-memory/InMemoryStorage.js +349 -0
- package/dist/src/storage/in-memory/InMemoryStorage.js.map +1 -0
- package/dist/src/storage/in-memory/index.d.ts +12 -0
- package/dist/src/storage/in-memory/index.d.ts.map +1 -0
- package/dist/src/storage/in-memory/index.js +12 -0
- package/dist/src/storage/in-memory/index.js.map +1 -0
- package/dist/src/storage/index.d.ts +18 -0
- package/dist/src/storage/index.d.ts.map +1 -0
- package/dist/src/storage/index.js +10 -0
- package/dist/src/storage/index.js.map +1 -0
- package/dist/src/storage/interfaces.d.ts +520 -0
- package/dist/src/storage/interfaces.d.ts.map +1 -0
- package/dist/src/storage/interfaces.js +6 -0
- package/dist/src/storage/interfaces.js.map +1 -0
- package/dist/src/storage/local/LocalBackend.d.ts +54 -0
- package/dist/src/storage/local/LocalBackend.d.ts.map +1 -0
- package/dist/src/storage/local/LocalBackend.js +141 -0
- package/dist/src/storage/local/LocalBackend.js.map +1 -0
- package/dist/src/storage/local/LocalLockService.d.ts +105 -0
- package/dist/src/storage/local/LocalLockService.d.ts.map +1 -0
- package/dist/src/storage/local/LocalLockService.js +342 -0
- package/dist/src/storage/local/LocalLockService.js.map +1 -0
- package/dist/src/storage/local/LocalLogStore.d.ts +23 -0
- package/dist/src/storage/local/LocalLogStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalLogStore.js +66 -0
- package/dist/src/storage/local/LocalLogStore.js.map +1 -0
- package/dist/src/storage/local/LocalObjectStore.d.ts +52 -0
- package/dist/src/storage/local/LocalObjectStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalObjectStore.js +287 -0
- package/dist/src/storage/local/LocalObjectStore.js.map +1 -0
- package/dist/src/storage/local/LocalRefStore.d.ts +50 -0
- package/dist/src/storage/local/LocalRefStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalRefStore.js +337 -0
- package/dist/src/storage/local/LocalRefStore.js.map +1 -0
- package/dist/src/storage/local/LocalRepoStore.d.ts +53 -0
- package/dist/src/storage/local/LocalRepoStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalRepoStore.js +353 -0
- package/dist/src/storage/local/LocalRepoStore.js.map +1 -0
- package/dist/src/storage/local/gc.d.ts +92 -0
- package/dist/src/storage/local/gc.d.ts.map +1 -0
- package/dist/src/storage/local/gc.js +322 -0
- package/dist/src/storage/local/gc.js.map +1 -0
- package/dist/src/storage/local/index.d.ts +17 -0
- package/dist/src/storage/local/index.d.ts.map +1 -0
- package/dist/src/storage/local/index.js +17 -0
- package/dist/src/storage/local/index.js.map +1 -0
- package/dist/src/storage/local/localHelpers.d.ts +25 -0
- package/dist/src/storage/local/localHelpers.d.ts.map +1 -0
- package/dist/src/storage/local/localHelpers.js +69 -0
- package/dist/src/storage/local/localHelpers.js.map +1 -0
- package/dist/src/{repository.d.ts → storage/local/repository.d.ts} +8 -4
- package/dist/src/storage/local/repository.d.ts.map +1 -0
- package/dist/src/{repository.js → storage/local/repository.js} +31 -29
- package/dist/src/storage/local/repository.js.map +1 -0
- package/dist/src/tasks.d.ts +16 -10
- package/dist/src/tasks.d.ts.map +1 -1
- package/dist/src/tasks.js +35 -41
- package/dist/src/tasks.js.map +1 -1
- package/dist/src/test-helpers.d.ts +4 -4
- package/dist/src/test-helpers.d.ts.map +1 -1
- package/dist/src/test-helpers.js +7 -21
- package/dist/src/test-helpers.js.map +1 -1
- package/dist/src/trees.d.ts +89 -27
- package/dist/src/trees.d.ts.map +1 -1
- package/dist/src/trees.js +218 -100
- package/dist/src/trees.js.map +1 -1
- package/dist/src/uuid.d.ts +26 -0
- package/dist/src/uuid.d.ts.map +1 -0
- package/dist/src/uuid.js +80 -0
- package/dist/src/uuid.js.map +1 -0
- package/dist/src/workspaceStatus.d.ts +6 -4
- package/dist/src/workspaceStatus.d.ts.map +1 -1
- package/dist/src/workspaceStatus.js +43 -49
- package/dist/src/workspaceStatus.js.map +1 -1
- package/dist/src/workspaces.d.ts +35 -26
- package/dist/src/workspaces.d.ts.map +1 -1
- package/dist/src/workspaces.js +169 -118
- package/dist/src/workspaces.js.map +1 -1
- package/package.json +4 -4
- package/dist/src/gc.d.ts +0 -54
- package/dist/src/gc.d.ts.map +0 -1
- package/dist/src/gc.js +0 -233
- package/dist/src/gc.js.map +0 -1
- package/dist/src/repository.d.ts.map +0 -1
- package/dist/src/repository.js.map +0 -1
- package/dist/src/workspaceLock.d.ts +0 -67
- package/dist/src/workspaceLock.d.ts.map +0 -1
- package/dist/src/workspaceLock.js +0 -217
- package/dist/src/workspaceLock.js.map +0 -1
package/dist/src/workspaces.d.ts
CHANGED
|
@@ -3,18 +3,27 @@
|
|
|
3
3
|
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
import type { WorkspaceState } from '@elaraai/e3-types';
|
|
6
|
-
import {
|
|
6
|
+
import type { StorageBackend, LockHandle } from './storage/interfaces.js';
|
|
7
|
+
/**
|
|
8
|
+
* List workspace names.
|
|
9
|
+
*
|
|
10
|
+
* @param storage - Storage backend
|
|
11
|
+
* @param repo - Repository identifier
|
|
12
|
+
* @returns Array of workspace names
|
|
13
|
+
*/
|
|
14
|
+
export declare function workspaceList(storage: StorageBackend, repo: string): Promise<string[]>;
|
|
7
15
|
/**
|
|
8
16
|
* Create an empty workspace.
|
|
9
17
|
*
|
|
10
18
|
* Creates an undeployed workspace (state file with null package info).
|
|
11
19
|
* Use workspaceDeploy to deploy a package.
|
|
12
20
|
*
|
|
13
|
-
* @param
|
|
21
|
+
* @param storage - Storage backend
|
|
22
|
+
* @param repo - Repository identifier
|
|
14
23
|
* @param name - Workspace name
|
|
15
24
|
* @throws {WorkspaceExistsError} If workspace already exists
|
|
16
25
|
*/
|
|
17
|
-
export declare function workspaceCreate(
|
|
26
|
+
export declare function workspaceCreate(storage: StorageBackend, repo: string, name: string): Promise<void>;
|
|
18
27
|
/**
|
|
19
28
|
* Options for workspace removal.
|
|
20
29
|
*/
|
|
@@ -24,7 +33,7 @@ export interface WorkspaceRemoveOptions {
|
|
|
24
33
|
* for releasing the lock after the operation. If not provided, workspaceRemove
|
|
25
34
|
* will acquire and release a lock internally.
|
|
26
35
|
*/
|
|
27
|
-
lock?:
|
|
36
|
+
lock?: LockHandle;
|
|
28
37
|
}
|
|
29
38
|
/**
|
|
30
39
|
* Remove a workspace.
|
|
@@ -34,38 +43,34 @@ export interface WorkspaceRemoveOptions {
|
|
|
34
43
|
* Acquires a workspace lock to prevent removing a workspace while a dataflow
|
|
35
44
|
* is running. Throws WorkspaceLockError if the workspace is currently locked.
|
|
36
45
|
*
|
|
37
|
-
* @param
|
|
46
|
+
* @param storage - Storage backend
|
|
47
|
+
* @param repo - Repository identifier
|
|
38
48
|
* @param name - Workspace name
|
|
39
49
|
* @param options - Optional settings including external lock
|
|
40
50
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
41
51
|
* @throws {WorkspaceLockError} If workspace is locked by another process
|
|
42
52
|
*/
|
|
43
|
-
export declare function workspaceRemove(
|
|
44
|
-
/**
|
|
45
|
-
* List workspace names.
|
|
46
|
-
*
|
|
47
|
-
* @param repoPath - Path to .e3 repository
|
|
48
|
-
* @returns Array of workspace names
|
|
49
|
-
*/
|
|
50
|
-
export declare function workspaceList(repoPath: string): Promise<string[]>;
|
|
53
|
+
export declare function workspaceRemove(storage: StorageBackend, repo: string, name: string, options?: WorkspaceRemoveOptions): Promise<void>;
|
|
51
54
|
/**
|
|
52
55
|
* Get the full state for a workspace.
|
|
53
56
|
*
|
|
54
|
-
* @param
|
|
57
|
+
* @param storage - Storage backend
|
|
58
|
+
* @param repo - Repository identifier
|
|
55
59
|
* @param name - Workspace name
|
|
56
60
|
* @returns Workspace state, or null if workspace doesn't exist or is not deployed
|
|
57
61
|
*/
|
|
58
|
-
export declare function workspaceGetState(
|
|
62
|
+
export declare function workspaceGetState(storage: StorageBackend, repo: string, name: string): Promise<WorkspaceState | null>;
|
|
59
63
|
/**
|
|
60
64
|
* Get the deployed package for a workspace.
|
|
61
65
|
*
|
|
62
|
-
* @param
|
|
66
|
+
* @param storage - Storage backend
|
|
67
|
+
* @param repo - Repository identifier
|
|
63
68
|
* @param name - Workspace name
|
|
64
69
|
* @returns Package name, version, and hash
|
|
65
70
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
66
71
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
67
72
|
*/
|
|
68
|
-
export declare function workspaceGetPackage(
|
|
73
|
+
export declare function workspaceGetPackage(storage: StorageBackend, repo: string, name: string): Promise<{
|
|
69
74
|
name: string;
|
|
70
75
|
version: string;
|
|
71
76
|
hash: string;
|
|
@@ -73,23 +78,25 @@ export declare function workspaceGetPackage(repoPath: string, name: string): Pro
|
|
|
73
78
|
/**
|
|
74
79
|
* Get the root tree hash for a workspace.
|
|
75
80
|
*
|
|
76
|
-
* @param
|
|
81
|
+
* @param storage - Storage backend
|
|
82
|
+
* @param repo - Repository identifier
|
|
77
83
|
* @param name - Workspace name
|
|
78
84
|
* @returns Root tree object hash
|
|
79
85
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
80
86
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
81
87
|
*/
|
|
82
|
-
export declare function workspaceGetRoot(
|
|
88
|
+
export declare function workspaceGetRoot(storage: StorageBackend, repo: string, name: string): Promise<string>;
|
|
83
89
|
/**
|
|
84
90
|
* Atomically update the root tree hash for a workspace.
|
|
85
91
|
*
|
|
86
|
-
* @param
|
|
92
|
+
* @param storage - Storage backend
|
|
93
|
+
* @param repo - Repository identifier
|
|
87
94
|
* @param name - Workspace name
|
|
88
95
|
* @param hash - New root tree object hash
|
|
89
96
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
90
97
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
91
98
|
*/
|
|
92
|
-
export declare function workspaceSetRoot(
|
|
99
|
+
export declare function workspaceSetRoot(storage: StorageBackend, repo: string, name: string, hash: string): Promise<void>;
|
|
93
100
|
/**
|
|
94
101
|
* Options for workspace deployment.
|
|
95
102
|
*/
|
|
@@ -99,7 +106,7 @@ export interface WorkspaceDeployOptions {
|
|
|
99
106
|
* for releasing the lock after the operation. If not provided, workspaceDeploy
|
|
100
107
|
* will acquire and release a lock internally.
|
|
101
108
|
*/
|
|
102
|
-
lock?:
|
|
109
|
+
lock?: LockHandle;
|
|
103
110
|
}
|
|
104
111
|
/**
|
|
105
112
|
* Deploy a package to a workspace.
|
|
@@ -111,14 +118,15 @@ export interface WorkspaceDeployOptions {
|
|
|
111
118
|
* or concurrent deploys. Throws WorkspaceLockError if the workspace is
|
|
112
119
|
* currently locked by another process.
|
|
113
120
|
*
|
|
114
|
-
* @param
|
|
121
|
+
* @param storage - Storage backend
|
|
122
|
+
* @param repo - Repository identifier
|
|
115
123
|
* @param name - Workspace name
|
|
116
124
|
* @param pkgName - Package name
|
|
117
125
|
* @param pkgVersion - Package version
|
|
118
126
|
* @param options - Optional settings including external lock
|
|
119
127
|
* @throws {WorkspaceLockError} If workspace is locked by another process
|
|
120
128
|
*/
|
|
121
|
-
export declare function workspaceDeploy(
|
|
129
|
+
export declare function workspaceDeploy(storage: StorageBackend, repo: string, name: string, pkgName: string, pkgVersion: string, options?: WorkspaceDeployOptions): Promise<void>;
|
|
122
130
|
/**
|
|
123
131
|
* Result of exporting a workspace
|
|
124
132
|
*/
|
|
@@ -137,7 +145,8 @@ export interface WorkspaceExportResult {
|
|
|
137
145
|
* 4. Collect all referenced objects
|
|
138
146
|
* 5. Write to .zip
|
|
139
147
|
*
|
|
140
|
-
* @param
|
|
148
|
+
* @param storage - Storage backend
|
|
149
|
+
* @param repo - Repository identifier
|
|
141
150
|
* @param name - Workspace name
|
|
142
151
|
* @param zipPath - Path to write the .zip file
|
|
143
152
|
* @param outputName - Package name (default: deployed package name)
|
|
@@ -146,5 +155,5 @@ export interface WorkspaceExportResult {
|
|
|
146
155
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
147
156
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
148
157
|
*/
|
|
149
|
-
export declare function workspaceExport(
|
|
158
|
+
export declare function workspaceExport(storage: StorageBackend, repo: string, name: string, zipPath: string, outputName?: string, version?: string): Promise<WorkspaceExportResult>;
|
|
150
159
|
//# sourceMappingURL=workspaces.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/workspaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/workspaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH,OAAO,KAAK,EAAiB,cAAc,EAAc,MAAM,mBAAmB,CAAC;AAQnF,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAE5F;AA0DD;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAMhC;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,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;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,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,UAAU,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAqCf;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;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,CAAC,CAoLhC"}
|
package/dist/src/workspaces.js
CHANGED
|
@@ -13,37 +13,30 @@
|
|
|
13
13
|
* State is stored in workspaces/<name>.beast2 as a single atomic file.
|
|
14
14
|
* No state file means the workspace does not exist.
|
|
15
15
|
*/
|
|
16
|
-
import * as fs from 'fs/promises';
|
|
17
16
|
import { createWriteStream } from 'fs';
|
|
18
|
-
import * as
|
|
17
|
+
import * as fs from 'fs/promises';
|
|
19
18
|
import yazl from 'yazl';
|
|
20
|
-
import { decodeBeast2For, encodeBeast2For } from '@elaraai/east';
|
|
21
|
-
import { PackageObjectType, WorkspaceStateType } from '@elaraai/e3-types';
|
|
22
|
-
import { objectRead, objectWrite } from './objects.js';
|
|
19
|
+
import { decodeBeast2For, encodeBeast2For, variant } from '@elaraai/east';
|
|
20
|
+
import { PackageObjectType, WorkspaceStateType, TaskObjectType, DataflowRunType } from '@elaraai/e3-types';
|
|
23
21
|
import { packageResolve, packageRead } from './packages.js';
|
|
24
|
-
import { WorkspaceNotFoundError, WorkspaceNotDeployedError, WorkspaceExistsError,
|
|
25
|
-
import { acquireWorkspaceLock } from './workspaceLock.js';
|
|
22
|
+
import { WorkspaceNotFoundError, WorkspaceNotDeployedError, WorkspaceExistsError, WorkspaceLockError, } from './errors.js';
|
|
26
23
|
/**
|
|
27
|
-
*
|
|
24
|
+
* List workspace names.
|
|
25
|
+
*
|
|
26
|
+
* @param storage - Storage backend
|
|
27
|
+
* @param repo - Repository identifier
|
|
28
|
+
* @returns Array of workspace names
|
|
28
29
|
*/
|
|
29
|
-
function
|
|
30
|
-
return
|
|
30
|
+
export async function workspaceList(storage, repo) {
|
|
31
|
+
return storage.refs.workspaceList(repo);
|
|
31
32
|
}
|
|
32
33
|
/**
|
|
33
|
-
*
|
|
34
|
+
* Write workspace state via storage backend.
|
|
34
35
|
*/
|
|
35
|
-
async function writeState(
|
|
36
|
-
const wsDir = path.join(repoPath, 'workspaces');
|
|
37
|
-
const stateFile = statePath(repoPath, name);
|
|
38
|
-
// Ensure workspaces directory exists
|
|
39
|
-
await fs.mkdir(wsDir, { recursive: true });
|
|
36
|
+
async function writeState(storage, repo, name, state) {
|
|
40
37
|
const encoder = encodeBeast2For(WorkspaceStateType);
|
|
41
38
|
const data = encoder(state);
|
|
42
|
-
|
|
43
|
-
const randomSuffix = Math.random().toString(36).slice(2, 10);
|
|
44
|
-
const tempPath = path.join(wsDir, `.${name}.${Date.now()}.${randomSuffix}.tmp`);
|
|
45
|
-
await fs.writeFile(tempPath, data);
|
|
46
|
-
await fs.rename(tempPath, stateFile);
|
|
39
|
+
await storage.refs.workspaceWrite(repo, name, data);
|
|
47
40
|
}
|
|
48
41
|
/**
|
|
49
42
|
* Read workspace state.
|
|
@@ -51,31 +44,25 @@ async function writeState(repoPath, name, state) {
|
|
|
51
44
|
* Returns { exists: true, deployed: false } if workspace exists but not deployed.
|
|
52
45
|
* Returns { exists: true, deployed: true, state } if workspace is deployed.
|
|
53
46
|
*/
|
|
54
|
-
async function readState(
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// Empty file means workspace exists but is not deployed
|
|
59
|
-
if (data.length === 0) {
|
|
60
|
-
return { exists: true, deployed: false };
|
|
61
|
-
}
|
|
62
|
-
const decoder = decodeBeast2For(WorkspaceStateType);
|
|
63
|
-
return { exists: true, deployed: true, state: decoder(data) };
|
|
47
|
+
async function readState(storage, repo, name) {
|
|
48
|
+
const data = await storage.refs.workspaceRead(repo, name);
|
|
49
|
+
if (data === null) {
|
|
50
|
+
return { exists: false };
|
|
64
51
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
throw err;
|
|
52
|
+
// Empty file means workspace exists but is not deployed
|
|
53
|
+
if (data.length === 0) {
|
|
54
|
+
return { exists: true, deployed: false };
|
|
70
55
|
}
|
|
56
|
+
const decoder = decodeBeast2For(WorkspaceStateType);
|
|
57
|
+
return { exists: true, deployed: true, state: decoder(Buffer.from(data)) };
|
|
71
58
|
}
|
|
72
59
|
/**
|
|
73
60
|
* Read workspace state, throwing if workspace doesn't exist or is not deployed.
|
|
74
61
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
75
62
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
76
63
|
*/
|
|
77
|
-
async function readStateOrThrow(
|
|
78
|
-
const result = await readState(
|
|
64
|
+
async function readStateOrThrow(storage, repo, name) {
|
|
65
|
+
const result = await readState(storage, repo, name);
|
|
79
66
|
if (!result.exists) {
|
|
80
67
|
throw new WorkspaceNotFoundError(name);
|
|
81
68
|
}
|
|
@@ -90,30 +77,19 @@ async function readStateOrThrow(repoPath, name) {
|
|
|
90
77
|
* Creates an undeployed workspace (state file with null package info).
|
|
91
78
|
* Use workspaceDeploy to deploy a package.
|
|
92
79
|
*
|
|
93
|
-
* @param
|
|
80
|
+
* @param storage - Storage backend
|
|
81
|
+
* @param repo - Repository identifier
|
|
94
82
|
* @param name - Workspace name
|
|
95
83
|
* @throws {WorkspaceExistsError} If workspace already exists
|
|
96
84
|
*/
|
|
97
|
-
export async function workspaceCreate(
|
|
98
|
-
const stateFile = statePath(repoPath, name);
|
|
85
|
+
export async function workspaceCreate(storage, repo, name) {
|
|
99
86
|
// Check if workspace already exists
|
|
100
|
-
|
|
101
|
-
|
|
87
|
+
const existing = await storage.refs.workspaceRead(repo, name);
|
|
88
|
+
if (existing !== null) {
|
|
102
89
|
throw new WorkspaceExistsError(name);
|
|
103
90
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
throw err;
|
|
107
|
-
if (!isNotFoundError(err)) {
|
|
108
|
-
throw err;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
// Create workspaces directory if needed
|
|
112
|
-
const wsDir = path.join(repoPath, 'workspaces');
|
|
113
|
-
await fs.mkdir(wsDir, { recursive: true });
|
|
114
|
-
// Create empty file to mark workspace as existing but not deployed
|
|
115
|
-
// We use an empty file rather than a state file since there's no valid state yet
|
|
116
|
-
await fs.writeFile(stateFile, '');
|
|
91
|
+
// Create empty state to mark workspace as existing but not deployed
|
|
92
|
+
await storage.refs.workspaceWrite(repo, name, new Uint8Array(0));
|
|
117
93
|
}
|
|
118
94
|
/**
|
|
119
95
|
* Remove a workspace.
|
|
@@ -123,27 +99,34 @@ export async function workspaceCreate(repoPath, name) {
|
|
|
123
99
|
* Acquires a workspace lock to prevent removing a workspace while a dataflow
|
|
124
100
|
* is running. Throws WorkspaceLockError if the workspace is currently locked.
|
|
125
101
|
*
|
|
126
|
-
* @param
|
|
102
|
+
* @param storage - Storage backend
|
|
103
|
+
* @param repo - Repository identifier
|
|
127
104
|
* @param name - Workspace name
|
|
128
105
|
* @param options - Optional settings including external lock
|
|
129
106
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
130
107
|
* @throws {WorkspaceLockError} If workspace is locked by another process
|
|
131
108
|
*/
|
|
132
|
-
export async function workspaceRemove(
|
|
109
|
+
export async function workspaceRemove(storage, repo, name, options = {}) {
|
|
133
110
|
// Acquire lock if not provided externally
|
|
134
111
|
const externalLock = options.lock;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
await
|
|
112
|
+
let lock = externalLock ?? null;
|
|
113
|
+
if (!lock) {
|
|
114
|
+
lock = await storage.locks.acquire(repo, name, variant('removal', null));
|
|
115
|
+
if (!lock) {
|
|
116
|
+
const state = await storage.locks.getState(repo, name);
|
|
117
|
+
throw new WorkspaceLockError(name, state ? {
|
|
118
|
+
acquiredAt: state.acquiredAt.toISOString(),
|
|
119
|
+
operation: state.operation.type,
|
|
120
|
+
} : undefined);
|
|
140
121
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
// Check if workspace exists
|
|
125
|
+
const existing = await storage.refs.workspaceRead(repo, name);
|
|
126
|
+
if (existing === null) {
|
|
127
|
+
throw new WorkspaceNotFoundError(name);
|
|
146
128
|
}
|
|
129
|
+
await storage.refs.workspaceRemove(repo, name);
|
|
147
130
|
}
|
|
148
131
|
finally {
|
|
149
132
|
// Only release the lock if we acquired it internally
|
|
@@ -152,37 +135,16 @@ export async function workspaceRemove(repoPath, name, options = {}) {
|
|
|
152
135
|
}
|
|
153
136
|
}
|
|
154
137
|
}
|
|
155
|
-
/**
|
|
156
|
-
* List workspace names.
|
|
157
|
-
*
|
|
158
|
-
* @param repoPath - Path to .e3 repository
|
|
159
|
-
* @returns Array of workspace names
|
|
160
|
-
*/
|
|
161
|
-
export async function workspaceList(repoPath) {
|
|
162
|
-
const workspacesDir = path.join(repoPath, 'workspaces');
|
|
163
|
-
const names = [];
|
|
164
|
-
try {
|
|
165
|
-
const entries = await fs.readdir(workspacesDir);
|
|
166
|
-
for (const entry of entries) {
|
|
167
|
-
if (entry.endsWith('.beast2')) {
|
|
168
|
-
names.push(entry.slice(0, -7)); // Remove .beast2 extension
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
catch {
|
|
173
|
-
// workspaces directory doesn't exist
|
|
174
|
-
}
|
|
175
|
-
return names;
|
|
176
|
-
}
|
|
177
138
|
/**
|
|
178
139
|
* Get the full state for a workspace.
|
|
179
140
|
*
|
|
180
|
-
* @param
|
|
141
|
+
* @param storage - Storage backend
|
|
142
|
+
* @param repo - Repository identifier
|
|
181
143
|
* @param name - Workspace name
|
|
182
144
|
* @returns Workspace state, or null if workspace doesn't exist or is not deployed
|
|
183
145
|
*/
|
|
184
|
-
export async function workspaceGetState(
|
|
185
|
-
const result = await readState(
|
|
146
|
+
export async function workspaceGetState(storage, repo, name) {
|
|
147
|
+
const result = await readState(storage, repo, name);
|
|
186
148
|
if (!result.exists || !result.deployed) {
|
|
187
149
|
return null;
|
|
188
150
|
}
|
|
@@ -191,14 +153,15 @@ export async function workspaceGetState(repoPath, name) {
|
|
|
191
153
|
/**
|
|
192
154
|
* Get the deployed package for a workspace.
|
|
193
155
|
*
|
|
194
|
-
* @param
|
|
156
|
+
* @param storage - Storage backend
|
|
157
|
+
* @param repo - Repository identifier
|
|
195
158
|
* @param name - Workspace name
|
|
196
159
|
* @returns Package name, version, and hash
|
|
197
160
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
198
161
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
199
162
|
*/
|
|
200
|
-
export async function workspaceGetPackage(
|
|
201
|
-
const state = await readStateOrThrow(
|
|
163
|
+
export async function workspaceGetPackage(storage, repo, name) {
|
|
164
|
+
const state = await readStateOrThrow(storage, repo, name);
|
|
202
165
|
return {
|
|
203
166
|
name: state.packageName,
|
|
204
167
|
version: state.packageVersion,
|
|
@@ -208,33 +171,35 @@ export async function workspaceGetPackage(repoPath, name) {
|
|
|
208
171
|
/**
|
|
209
172
|
* Get the root tree hash for a workspace.
|
|
210
173
|
*
|
|
211
|
-
* @param
|
|
174
|
+
* @param storage - Storage backend
|
|
175
|
+
* @param repo - Repository identifier
|
|
212
176
|
* @param name - Workspace name
|
|
213
177
|
* @returns Root tree object hash
|
|
214
178
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
215
179
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
216
180
|
*/
|
|
217
|
-
export async function workspaceGetRoot(
|
|
218
|
-
const state = await readStateOrThrow(
|
|
181
|
+
export async function workspaceGetRoot(storage, repo, name) {
|
|
182
|
+
const state = await readStateOrThrow(storage, repo, name);
|
|
219
183
|
return state.rootHash;
|
|
220
184
|
}
|
|
221
185
|
/**
|
|
222
186
|
* Atomically update the root tree hash for a workspace.
|
|
223
187
|
*
|
|
224
|
-
* @param
|
|
188
|
+
* @param storage - Storage backend
|
|
189
|
+
* @param repo - Repository identifier
|
|
225
190
|
* @param name - Workspace name
|
|
226
191
|
* @param hash - New root tree object hash
|
|
227
192
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
228
193
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
229
194
|
*/
|
|
230
|
-
export async function workspaceSetRoot(
|
|
231
|
-
const state = await readStateOrThrow(
|
|
195
|
+
export async function workspaceSetRoot(storage, repo, name, hash) {
|
|
196
|
+
const state = await readStateOrThrow(storage, repo, name);
|
|
232
197
|
const newState = {
|
|
233
198
|
...state,
|
|
234
199
|
rootHash: hash,
|
|
235
200
|
rootUpdatedAt: new Date(),
|
|
236
201
|
};
|
|
237
|
-
await writeState(
|
|
202
|
+
await writeState(storage, repo, name, newState);
|
|
238
203
|
}
|
|
239
204
|
/**
|
|
240
205
|
* Deploy a package to a workspace.
|
|
@@ -246,21 +211,32 @@ export async function workspaceSetRoot(repoPath, name, hash) {
|
|
|
246
211
|
* or concurrent deploys. Throws WorkspaceLockError if the workspace is
|
|
247
212
|
* currently locked by another process.
|
|
248
213
|
*
|
|
249
|
-
* @param
|
|
214
|
+
* @param storage - Storage backend
|
|
215
|
+
* @param repo - Repository identifier
|
|
250
216
|
* @param name - Workspace name
|
|
251
217
|
* @param pkgName - Package name
|
|
252
218
|
* @param pkgVersion - Package version
|
|
253
219
|
* @param options - Optional settings including external lock
|
|
254
220
|
* @throws {WorkspaceLockError} If workspace is locked by another process
|
|
255
221
|
*/
|
|
256
|
-
export async function workspaceDeploy(
|
|
222
|
+
export async function workspaceDeploy(storage, repo, name, pkgName, pkgVersion, options = {}) {
|
|
257
223
|
// Acquire lock if not provided externally
|
|
258
224
|
const externalLock = options.lock;
|
|
259
|
-
|
|
225
|
+
let lock = externalLock ?? null;
|
|
226
|
+
if (!lock) {
|
|
227
|
+
lock = await storage.locks.acquire(repo, name, variant('deployment', null));
|
|
228
|
+
if (!lock) {
|
|
229
|
+
const state = await storage.locks.getState(repo, name);
|
|
230
|
+
throw new WorkspaceLockError(name, state ? {
|
|
231
|
+
acquiredAt: state.acquiredAt.toISOString(),
|
|
232
|
+
operation: state.operation.type,
|
|
233
|
+
} : undefined);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
260
236
|
try {
|
|
261
237
|
// Resolve package hash and read package object
|
|
262
|
-
const packageHash = await packageResolve(
|
|
263
|
-
const pkg = await packageRead(
|
|
238
|
+
const packageHash = await packageResolve(storage, repo, pkgName, pkgVersion);
|
|
239
|
+
const pkg = await packageRead(storage, repo, pkgName, pkgVersion);
|
|
264
240
|
const now = new Date();
|
|
265
241
|
const state = {
|
|
266
242
|
packageName: pkgName,
|
|
@@ -269,8 +245,9 @@ export async function workspaceDeploy(repoPath, name, pkgName, pkgVersion, optio
|
|
|
269
245
|
deployedAt: now,
|
|
270
246
|
rootHash: pkg.data.value,
|
|
271
247
|
rootUpdatedAt: now,
|
|
248
|
+
currentRunId: variant('none', null),
|
|
272
249
|
};
|
|
273
|
-
await writeState(
|
|
250
|
+
await writeState(storage, repo, name, state);
|
|
274
251
|
}
|
|
275
252
|
finally {
|
|
276
253
|
// Only release the lock if we acquired it internally
|
|
@@ -292,7 +269,8 @@ const DETERMINISTIC_MTIME = new Date(0);
|
|
|
292
269
|
* 4. Collect all referenced objects
|
|
293
270
|
* 5. Write to .zip
|
|
294
271
|
*
|
|
295
|
-
* @param
|
|
272
|
+
* @param storage - Storage backend
|
|
273
|
+
* @param repo - Repository identifier
|
|
296
274
|
* @param name - Workspace name
|
|
297
275
|
* @param zipPath - Path to write the .zip file
|
|
298
276
|
* @param outputName - Package name (default: deployed package name)
|
|
@@ -301,12 +279,12 @@ const DETERMINISTIC_MTIME = new Date(0);
|
|
|
301
279
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
302
280
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
303
281
|
*/
|
|
304
|
-
export async function workspaceExport(
|
|
282
|
+
export async function workspaceExport(storage, repo, name, zipPath, outputName, version) {
|
|
305
283
|
const partialPath = `${zipPath}.partial`;
|
|
306
284
|
// Get workspace state
|
|
307
|
-
const state = await readStateOrThrow(
|
|
285
|
+
const state = await readStateOrThrow(storage, repo, name);
|
|
308
286
|
// Read the deployed package object using the stored hash
|
|
309
|
-
const deployedPkgData = await
|
|
287
|
+
const deployedPkgData = await storage.objects.read(repo, state.packageHash);
|
|
310
288
|
const decoder = decodeBeast2For(PackageObjectType);
|
|
311
289
|
const deployedPkgObject = decoder(Buffer.from(deployedPkgData));
|
|
312
290
|
// Determine output name and version
|
|
@@ -323,7 +301,7 @@ export async function workspaceExport(repoPath, name, zipPath, outputName, versi
|
|
|
323
301
|
// Encode and store the new package object
|
|
324
302
|
const encoder = encodeBeast2For(PackageObjectType);
|
|
325
303
|
const pkgData = encoder(newPkgObject);
|
|
326
|
-
const packageHash = await
|
|
304
|
+
const packageHash = await storage.objects.write(repo, pkgData);
|
|
327
305
|
// Create zip file
|
|
328
306
|
const zipfile = new yazl.ZipFile();
|
|
329
307
|
// Track which objects we've added to avoid duplicates
|
|
@@ -333,7 +311,7 @@ export async function workspaceExport(repoPath, name, zipPath, outputName, versi
|
|
|
333
311
|
if (addedObjects.has(hash))
|
|
334
312
|
return;
|
|
335
313
|
addedObjects.add(hash);
|
|
336
|
-
const data = await
|
|
314
|
+
const data = await storage.objects.read(repo, hash);
|
|
337
315
|
const objPath = `objects/${hash.slice(0, 2)}/${hash.slice(2)}.beast2`;
|
|
338
316
|
zipfile.addBuffer(Buffer.from(data), objPath, { mtime: DETERMINISTIC_MTIME });
|
|
339
317
|
};
|
|
@@ -348,7 +326,7 @@ export async function workspaceExport(repoPath, name, zipPath, outputName, versi
|
|
|
348
326
|
continue;
|
|
349
327
|
try {
|
|
350
328
|
await addObject(potentialHash);
|
|
351
|
-
const childData = await
|
|
329
|
+
const childData = await storage.objects.read(repo, potentialHash);
|
|
352
330
|
await collectTreeChildren(childData);
|
|
353
331
|
}
|
|
354
332
|
catch {
|
|
@@ -358,17 +336,90 @@ export async function workspaceExport(repoPath, name, zipPath, outputName, versi
|
|
|
358
336
|
};
|
|
359
337
|
// Add the package object
|
|
360
338
|
await addObject(packageHash);
|
|
361
|
-
// Collect all task objects
|
|
339
|
+
// Collect all task objects and their commandIr references
|
|
340
|
+
const taskDecoder = decodeBeast2For(TaskObjectType);
|
|
362
341
|
for (const taskHash of newPkgObject.tasks.values()) {
|
|
363
342
|
await addObject(taskHash);
|
|
343
|
+
// Task objects contain commandIr hashes that must also be exported
|
|
344
|
+
const taskData = await storage.objects.read(repo, taskHash);
|
|
345
|
+
const taskObject = taskDecoder(Buffer.from(taskData));
|
|
346
|
+
// The commandIr is a hash reference to an IR object
|
|
347
|
+
await addObject(taskObject.commandIr);
|
|
348
|
+
// Recursively collect any objects referenced by the IR
|
|
349
|
+
const irData = await storage.objects.read(repo, taskObject.commandIr);
|
|
350
|
+
await collectTreeChildren(irData);
|
|
364
351
|
}
|
|
365
352
|
// Collect the root tree and all its children
|
|
366
353
|
await addObject(state.rootHash);
|
|
367
|
-
const rootTreeData = await
|
|
354
|
+
const rootTreeData = await storage.objects.read(repo, state.rootHash);
|
|
368
355
|
await collectTreeChildren(rootTreeData);
|
|
369
356
|
// Write the package ref
|
|
370
357
|
const refPath = `packages/${finalName}/${finalVersion}`;
|
|
371
358
|
zipfile.addBuffer(Buffer.from(packageHash + '\n'), refPath, { mtime: DETERMINISTIC_MTIME });
|
|
359
|
+
// Include executions and logs if currentRunId exists
|
|
360
|
+
if (state.currentRunId.type === 'some') {
|
|
361
|
+
const currentRunId = state.currentRunId.value;
|
|
362
|
+
const dataflowRun = await storage.refs.dataflowRunGet(repo, name, currentRunId);
|
|
363
|
+
if (dataflowRun) {
|
|
364
|
+
// Write the dataflow run record
|
|
365
|
+
const runEncoder = encodeBeast2For(DataflowRunType);
|
|
366
|
+
const dataflowPath = `dataflows/${name}/${currentRunId}.beast2`;
|
|
367
|
+
zipfile.addBuffer(Buffer.from(runEncoder(dataflowRun)), dataflowPath, { mtime: DETERMINISTIC_MTIME });
|
|
368
|
+
// Include execution files for each task
|
|
369
|
+
for (const [taskName, execRecord] of dataflowRun.taskExecutions) {
|
|
370
|
+
const taskHash = newPkgObject.tasks.get(taskName);
|
|
371
|
+
if (!taskHash)
|
|
372
|
+
continue;
|
|
373
|
+
// Get the task to find its inputs
|
|
374
|
+
const taskData = await storage.objects.read(repo, taskHash);
|
|
375
|
+
const task = taskDecoder(Buffer.from(taskData));
|
|
376
|
+
// Compute inputsHash
|
|
377
|
+
const inputHashes = [];
|
|
378
|
+
for (const inputPath of task.inputs) {
|
|
379
|
+
try {
|
|
380
|
+
// Read input hash from the workspace at export time
|
|
381
|
+
// These should match what was used during execution
|
|
382
|
+
const { workspaceGetDatasetHash } = await import('./trees.js');
|
|
383
|
+
const { hash } = await workspaceGetDatasetHash(storage, repo, name, inputPath);
|
|
384
|
+
if (hash)
|
|
385
|
+
inputHashes.push(hash);
|
|
386
|
+
}
|
|
387
|
+
catch {
|
|
388
|
+
// Skip if input not available
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (inputHashes.length !== task.inputs.length)
|
|
392
|
+
continue;
|
|
393
|
+
const { inputsHash } = await import('./executions.js');
|
|
394
|
+
const inHash = inputsHash(inputHashes);
|
|
395
|
+
// Read and add execution status
|
|
396
|
+
const execStatus = await storage.refs.executionGet(repo, taskHash, inHash, execRecord.executionId);
|
|
397
|
+
if (execStatus) {
|
|
398
|
+
const statusEncoder = await import('@elaraai/e3-types').then(m => encodeBeast2For(m.ExecutionStatusType));
|
|
399
|
+
const statusPath = `executions/${taskHash}/${inHash}/${execRecord.executionId}/status.beast2`;
|
|
400
|
+
zipfile.addBuffer(Buffer.from(statusEncoder(execStatus)), statusPath, { mtime: DETERMINISTIC_MTIME });
|
|
401
|
+
// Add output file if success
|
|
402
|
+
if (execStatus.type === 'success') {
|
|
403
|
+
const outputPath = `executions/${taskHash}/${inHash}/${execRecord.executionId}/output`;
|
|
404
|
+
zipfile.addBuffer(Buffer.from(execStatus.value.outputHash + '\n'), outputPath, { mtime: DETERMINISTIC_MTIME });
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// Read and add logs (stdout/stderr)
|
|
408
|
+
for (const stream of ['stdout', 'stderr']) {
|
|
409
|
+
try {
|
|
410
|
+
const logChunk = await storage.logs.read(repo, taskHash, inHash, execRecord.executionId, stream, { limit: 100 * 1024 * 1024 });
|
|
411
|
+
if (logChunk.data && logChunk.data.length > 0) {
|
|
412
|
+
const logPath = `executions/${taskHash}/${inHash}/${execRecord.executionId}/${stream}.txt`;
|
|
413
|
+
zipfile.addBuffer(Buffer.from(logChunk.data), logPath, { mtime: DETERMINISTIC_MTIME });
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
catch {
|
|
417
|
+
// Skip if log not available
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
372
423
|
// Finalize and write zip to disk
|
|
373
424
|
await new Promise((resolve, reject) => {
|
|
374
425
|
const writeStream = createWriteStream(partialPath);
|