@elaraai/e3-core 0.0.1-beta.0
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/LICENSE.md +50 -0
- package/README.md +76 -0
- package/dist/src/dataflow.d.ts +96 -0
- package/dist/src/dataflow.d.ts.map +1 -0
- package/dist/src/dataflow.js +433 -0
- package/dist/src/dataflow.js.map +1 -0
- package/dist/src/errors.d.ts +87 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +178 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/executions.d.ts +163 -0
- package/dist/src/executions.d.ts.map +1 -0
- package/dist/src/executions.js +535 -0
- package/dist/src/executions.js.map +1 -0
- package/dist/src/formats.d.ts +38 -0
- package/dist/src/formats.d.ts.map +1 -0
- package/dist/src/formats.js +115 -0
- package/dist/src/formats.js.map +1 -0
- package/dist/src/gc.d.ts +54 -0
- package/dist/src/gc.d.ts.map +1 -0
- package/dist/src/gc.js +232 -0
- package/dist/src/gc.js.map +1 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +68 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/objects.d.ts +62 -0
- package/dist/src/objects.d.ts.map +1 -0
- package/dist/src/objects.js +245 -0
- package/dist/src/objects.js.map +1 -0
- package/dist/src/packages.d.ts +85 -0
- package/dist/src/packages.d.ts.map +1 -0
- package/dist/src/packages.js +355 -0
- package/dist/src/packages.js.map +1 -0
- package/dist/src/repository.d.ts +38 -0
- package/dist/src/repository.d.ts.map +1 -0
- package/dist/src/repository.js +103 -0
- package/dist/src/repository.js.map +1 -0
- package/dist/src/tasks.d.ts +63 -0
- package/dist/src/tasks.d.ts.map +1 -0
- package/dist/src/tasks.js +145 -0
- package/dist/src/tasks.js.map +1 -0
- package/dist/src/test-helpers.d.ts +44 -0
- package/dist/src/test-helpers.d.ts.map +1 -0
- package/dist/src/test-helpers.js +141 -0
- package/dist/src/test-helpers.js.map +1 -0
- package/dist/src/trees.d.ts +156 -0
- package/dist/src/trees.d.ts.map +1 -0
- package/dist/src/trees.js +607 -0
- package/dist/src/trees.js.map +1 -0
- package/dist/src/workspaces.d.ts +116 -0
- package/dist/src/workspaces.d.ts.map +1 -0
- package/dist/src/workspaces.js +356 -0
- package/dist/src/workspaces.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Task operations for e3 repositories.
|
|
7
|
+
*
|
|
8
|
+
* Tasks are computations with input/output dataset paths. They are stored
|
|
9
|
+
* as TaskObjects in the object store and referenced by packages via their hash.
|
|
10
|
+
*
|
|
11
|
+
* This module provides APIs to:
|
|
12
|
+
* - List tasks in packages and workspaces
|
|
13
|
+
* - Get task details (runner, inputs, output paths)
|
|
14
|
+
*/
|
|
15
|
+
import { decodeBeast2For } from '@elaraai/east';
|
|
16
|
+
import { PackageObjectType, TaskObjectType, WorkspaceStateType, } from '@elaraai/e3-types';
|
|
17
|
+
import { objectRead } from './objects.js';
|
|
18
|
+
import { packageRead } from './packages.js';
|
|
19
|
+
import { TaskNotFoundError, WorkspaceNotFoundError, WorkspaceNotDeployedError, isNotFoundError, } from './errors.js';
|
|
20
|
+
import * as fs from 'fs/promises';
|
|
21
|
+
import * as path from 'path';
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// Package Task Operations
|
|
24
|
+
// =============================================================================
|
|
25
|
+
/**
|
|
26
|
+
* List task names in a package.
|
|
27
|
+
*
|
|
28
|
+
* @param repoPath - Path to .e3 repository
|
|
29
|
+
* @param name - Package name
|
|
30
|
+
* @param version - Package version
|
|
31
|
+
* @returns Array of task names
|
|
32
|
+
* @throws If package not found
|
|
33
|
+
*/
|
|
34
|
+
export async function packageListTasks(repoPath, name, version) {
|
|
35
|
+
const pkg = await packageRead(repoPath, name, version);
|
|
36
|
+
return Array.from(pkg.tasks.keys());
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get task details from a package.
|
|
40
|
+
*
|
|
41
|
+
* @param repoPath - Path to .e3 repository
|
|
42
|
+
* @param name - Package name
|
|
43
|
+
* @param version - Package version
|
|
44
|
+
* @param taskName - Name of the task
|
|
45
|
+
* @returns The TaskObject containing runner, inputs, and output
|
|
46
|
+
* @throws {PackageNotFoundError} If package not found
|
|
47
|
+
* @throws {TaskNotFoundError} If task not found in package
|
|
48
|
+
*/
|
|
49
|
+
export async function packageGetTask(repoPath, name, version, taskName) {
|
|
50
|
+
const pkg = await packageRead(repoPath, name, version);
|
|
51
|
+
const taskHash = pkg.tasks.get(taskName);
|
|
52
|
+
if (!taskHash) {
|
|
53
|
+
throw new TaskNotFoundError(taskName);
|
|
54
|
+
}
|
|
55
|
+
const taskData = await objectRead(repoPath, taskHash);
|
|
56
|
+
const decoder = decodeBeast2For(TaskObjectType);
|
|
57
|
+
return decoder(Buffer.from(taskData));
|
|
58
|
+
}
|
|
59
|
+
// =============================================================================
|
|
60
|
+
// Workspace Task Operations
|
|
61
|
+
// =============================================================================
|
|
62
|
+
/**
|
|
63
|
+
* Read workspace state from file.
|
|
64
|
+
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
65
|
+
* @throws {WorkspaceNotDeployedError} If workspace exists but not deployed
|
|
66
|
+
*/
|
|
67
|
+
async function readWorkspaceState(repoPath, ws) {
|
|
68
|
+
const stateFile = path.join(repoPath, 'workspaces', `${ws}.beast2`);
|
|
69
|
+
try {
|
|
70
|
+
const data = await fs.readFile(stateFile);
|
|
71
|
+
if (data.length === 0) {
|
|
72
|
+
throw new WorkspaceNotDeployedError(ws);
|
|
73
|
+
}
|
|
74
|
+
const decoder = decodeBeast2For(WorkspaceStateType);
|
|
75
|
+
return decoder(data);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
if (err instanceof WorkspaceNotDeployedError)
|
|
79
|
+
throw err;
|
|
80
|
+
if (isNotFoundError(err)) {
|
|
81
|
+
throw new WorkspaceNotFoundError(ws);
|
|
82
|
+
}
|
|
83
|
+
throw err;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the deployed package object for a workspace.
|
|
88
|
+
*/
|
|
89
|
+
async function getWorkspacePackageObject(repoPath, ws) {
|
|
90
|
+
const state = await readWorkspaceState(repoPath, ws);
|
|
91
|
+
const pkgData = await objectRead(repoPath, state.packageHash);
|
|
92
|
+
const decoder = decodeBeast2For(PackageObjectType);
|
|
93
|
+
return decoder(Buffer.from(pkgData));
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* List task names in a workspace.
|
|
97
|
+
*
|
|
98
|
+
* Tasks are defined by the deployed package.
|
|
99
|
+
*
|
|
100
|
+
* @param repoPath - Path to .e3 repository
|
|
101
|
+
* @param ws - Workspace name
|
|
102
|
+
* @returns Array of task names
|
|
103
|
+
* @throws If workspace not found or not deployed
|
|
104
|
+
*/
|
|
105
|
+
export async function workspaceListTasks(repoPath, ws) {
|
|
106
|
+
const pkg = await getWorkspacePackageObject(repoPath, ws);
|
|
107
|
+
return Array.from(pkg.tasks.keys());
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get task hash from a workspace.
|
|
111
|
+
*
|
|
112
|
+
* @param repoPath - Path to .e3 repository
|
|
113
|
+
* @param ws - Workspace name
|
|
114
|
+
* @param taskName - Name of the task
|
|
115
|
+
* @returns The hash of the TaskObject
|
|
116
|
+
* @throws {WorkspaceNotFoundError} If workspace not found
|
|
117
|
+
* @throws {WorkspaceNotDeployedError} If workspace not deployed
|
|
118
|
+
* @throws {TaskNotFoundError} If task not found
|
|
119
|
+
*/
|
|
120
|
+
export async function workspaceGetTaskHash(repoPath, ws, taskName) {
|
|
121
|
+
const pkg = await getWorkspacePackageObject(repoPath, ws);
|
|
122
|
+
const taskHash = pkg.tasks.get(taskName);
|
|
123
|
+
if (!taskHash) {
|
|
124
|
+
throw new TaskNotFoundError(taskName);
|
|
125
|
+
}
|
|
126
|
+
return taskHash;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get task details from a workspace.
|
|
130
|
+
*
|
|
131
|
+
* Tasks are defined by the deployed package.
|
|
132
|
+
*
|
|
133
|
+
* @param repoPath - Path to .e3 repository
|
|
134
|
+
* @param ws - Workspace name
|
|
135
|
+
* @param taskName - Name of the task
|
|
136
|
+
* @returns The TaskObject containing runner, inputs, and output
|
|
137
|
+
* @throws If workspace not deployed or task not found
|
|
138
|
+
*/
|
|
139
|
+
export async function workspaceGetTask(repoPath, ws, taskName) {
|
|
140
|
+
const taskHash = await workspaceGetTaskHash(repoPath, ws, taskName);
|
|
141
|
+
const taskData = await objectRead(repoPath, taskHash);
|
|
142
|
+
const decoder = decodeBeast2For(TaskObjectType);
|
|
143
|
+
return decoder(Buffer.from(taskData));
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Creates a temporary directory for testing
|
|
7
|
+
* @returns Path to temporary directory
|
|
8
|
+
*/
|
|
9
|
+
export declare function createTempDir(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Removes a temporary directory and all its contents
|
|
12
|
+
* @param dir Path to directory to remove
|
|
13
|
+
*/
|
|
14
|
+
export declare function removeTempDir(dir: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a temporary e3 repository for testing
|
|
17
|
+
* @returns Path to .e3 directory
|
|
18
|
+
*/
|
|
19
|
+
export declare function createTestRepo(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Remove a test repository (removes parent directory)
|
|
22
|
+
* @param e3Dir Path to .e3 directory
|
|
23
|
+
*/
|
|
24
|
+
export declare function removeTestRepo(e3Dir: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Read all entries from a zip file
|
|
27
|
+
* @param zipPath Path to zip file
|
|
28
|
+
* @returns Map of entry path to content buffer
|
|
29
|
+
*/
|
|
30
|
+
export declare function readZipEntries(zipPath: string): Promise<Map<string, Buffer>>;
|
|
31
|
+
/**
|
|
32
|
+
* Compare two zip files for content equality.
|
|
33
|
+
* Returns true if both zips have the same entries with the same content.
|
|
34
|
+
* Does not compare timestamps or other metadata.
|
|
35
|
+
*
|
|
36
|
+
* @param zipPath1 Path to first zip file
|
|
37
|
+
* @param zipPath2 Path to second zip file
|
|
38
|
+
* @returns Object with equal flag and optional diff info
|
|
39
|
+
*/
|
|
40
|
+
export declare function zipEqual(zipPath1: string, zipPath2: string): Promise<{
|
|
41
|
+
equal: boolean;
|
|
42
|
+
diff?: string;
|
|
43
|
+
}>;
|
|
44
|
+
//# sourceMappingURL=test-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../../src/test-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAOD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CASvC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CASlD;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAgClF;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoC5C"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Test helpers for e3-core
|
|
7
|
+
* Provides utilities for setting up and tearing down test repositories
|
|
8
|
+
*/
|
|
9
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
10
|
+
import { tmpdir } from 'node:os';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import yauzl from 'yauzl';
|
|
13
|
+
import { repoInit } from './repository.js';
|
|
14
|
+
/**
|
|
15
|
+
* Creates a temporary directory for testing
|
|
16
|
+
* @returns Path to temporary directory
|
|
17
|
+
*/
|
|
18
|
+
export function createTempDir() {
|
|
19
|
+
return mkdtempSync(join(tmpdir(), 'e3-test-'));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Removes a temporary directory and all its contents
|
|
23
|
+
* @param dir Path to directory to remove
|
|
24
|
+
*/
|
|
25
|
+
export function removeTempDir(dir) {
|
|
26
|
+
rmSync(dir, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Track parent directories for cleanup
|
|
30
|
+
*/
|
|
31
|
+
const parentDirs = new Map();
|
|
32
|
+
/**
|
|
33
|
+
* Creates a temporary e3 repository for testing
|
|
34
|
+
* @returns Path to .e3 directory
|
|
35
|
+
*/
|
|
36
|
+
export function createTestRepo() {
|
|
37
|
+
const dir = createTempDir();
|
|
38
|
+
const result = repoInit(dir);
|
|
39
|
+
if (!result.success) {
|
|
40
|
+
throw new Error(`Failed to create test repository: ${result.error?.message}`);
|
|
41
|
+
}
|
|
42
|
+
// Track parent directory for cleanup
|
|
43
|
+
parentDirs.set(result.e3Dir, dir);
|
|
44
|
+
return result.e3Dir;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Remove a test repository (removes parent directory)
|
|
48
|
+
* @param e3Dir Path to .e3 directory
|
|
49
|
+
*/
|
|
50
|
+
export function removeTestRepo(e3Dir) {
|
|
51
|
+
const parentDir = parentDirs.get(e3Dir);
|
|
52
|
+
if (parentDir) {
|
|
53
|
+
removeTempDir(parentDir);
|
|
54
|
+
parentDirs.delete(e3Dir);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Fallback: remove the .e3 directory itself
|
|
58
|
+
removeTempDir(e3Dir);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Read all entries from a zip file
|
|
63
|
+
* @param zipPath Path to zip file
|
|
64
|
+
* @returns Map of entry path to content buffer
|
|
65
|
+
*/
|
|
66
|
+
export async function readZipEntries(zipPath) {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
yauzl.open(zipPath, { lazyEntries: true }, (err, zipfile) => {
|
|
69
|
+
if (err)
|
|
70
|
+
return reject(err);
|
|
71
|
+
if (!zipfile)
|
|
72
|
+
return reject(new Error('No zipfile'));
|
|
73
|
+
const entries = new Map();
|
|
74
|
+
zipfile.readEntry();
|
|
75
|
+
zipfile.on('entry', (entry) => {
|
|
76
|
+
if (/\/$/.test(entry.fileName)) {
|
|
77
|
+
// Directory entry, skip
|
|
78
|
+
zipfile.readEntry();
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
zipfile.openReadStream(entry, (err, readStream) => {
|
|
82
|
+
if (err)
|
|
83
|
+
return reject(err);
|
|
84
|
+
if (!readStream)
|
|
85
|
+
return reject(new Error('No read stream'));
|
|
86
|
+
const chunks = [];
|
|
87
|
+
readStream.on('data', (chunk) => chunks.push(chunk));
|
|
88
|
+
readStream.on('end', () => {
|
|
89
|
+
entries.set(entry.fileName, Buffer.concat(chunks));
|
|
90
|
+
zipfile.readEntry();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
zipfile.on('end', () => resolve(entries));
|
|
96
|
+
zipfile.on('error', reject);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Compare two zip files for content equality.
|
|
102
|
+
* Returns true if both zips have the same entries with the same content.
|
|
103
|
+
* Does not compare timestamps or other metadata.
|
|
104
|
+
*
|
|
105
|
+
* @param zipPath1 Path to first zip file
|
|
106
|
+
* @param zipPath2 Path to second zip file
|
|
107
|
+
* @returns Object with equal flag and optional diff info
|
|
108
|
+
*/
|
|
109
|
+
export async function zipEqual(zipPath1, zipPath2) {
|
|
110
|
+
const entries1 = await readZipEntries(zipPath1);
|
|
111
|
+
const entries2 = await readZipEntries(zipPath2);
|
|
112
|
+
// Check for missing entries
|
|
113
|
+
const keys1 = Array.from(entries1.keys()).sort();
|
|
114
|
+
const keys2 = Array.from(entries2.keys()).sort();
|
|
115
|
+
if (keys1.length !== keys2.length) {
|
|
116
|
+
return {
|
|
117
|
+
equal: false,
|
|
118
|
+
diff: `Entry count differs: ${keys1.length} vs ${keys2.length}`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
for (let i = 0; i < keys1.length; i++) {
|
|
122
|
+
if (keys1[i] !== keys2[i]) {
|
|
123
|
+
return {
|
|
124
|
+
equal: false,
|
|
125
|
+
diff: `Entry paths differ at index ${i}: ${keys1[i]} vs ${keys2[i]}`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Check content equality
|
|
130
|
+
for (const [path, data1] of entries1) {
|
|
131
|
+
const data2 = entries2.get(path);
|
|
132
|
+
if (!data1.equals(data2)) {
|
|
133
|
+
return {
|
|
134
|
+
equal: false,
|
|
135
|
+
diff: `Content differs at ${path}: ${data1.length} bytes vs ${data2.length} bytes`,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return { equal: true };
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=test-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../../src/test-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Low-level tree and dataset operations for e3 repositories.
|
|
7
|
+
*
|
|
8
|
+
* Trees are persistent data structures with structural sharing (like git trees).
|
|
9
|
+
* Each tree node contains DataRefs pointing to either other trees or dataset values.
|
|
10
|
+
*
|
|
11
|
+
* Tree operations require a Structure parameter which describes the shape of the
|
|
12
|
+
* tree node. This enables proper encoding/decoding with the correct StructType
|
|
13
|
+
* and supports future tree types (array, variant, etc.).
|
|
14
|
+
*
|
|
15
|
+
* Low-level operations work with hashes directly (by-hash).
|
|
16
|
+
* High-level operations traverse paths from a root (by-path).
|
|
17
|
+
*/
|
|
18
|
+
import { type EastType, type EastTypeValue } from '@elaraai/east';
|
|
19
|
+
import { type DataRef, type Structure, type TreePath } from '@elaraai/e3-types';
|
|
20
|
+
/**
|
|
21
|
+
* A tree object: mapping of field names to data references.
|
|
22
|
+
*
|
|
23
|
+
* This is a plain object (not a Map) because tree objects are encoded as
|
|
24
|
+
* StructTypes with known field names derived from the Structure.
|
|
25
|
+
*/
|
|
26
|
+
export type TreeObject = Record<string, DataRef>;
|
|
27
|
+
/**
|
|
28
|
+
* Read and decode a tree object from the object store.
|
|
29
|
+
*
|
|
30
|
+
* @param repoPath - Path to .e3 repository
|
|
31
|
+
* @param hash - Hash of the tree object
|
|
32
|
+
* @param structure - The structure describing this tree node's shape
|
|
33
|
+
* @returns The decoded tree object (field name -> DataRef)
|
|
34
|
+
* @throws If object not found, structure is not a tree, or decoding fails
|
|
35
|
+
*/
|
|
36
|
+
export declare function treeRead(repoPath: string, hash: string, structure: Structure): Promise<TreeObject>;
|
|
37
|
+
/**
|
|
38
|
+
* Encode and write a tree object to the object store.
|
|
39
|
+
*
|
|
40
|
+
* @param repoPath - Path to .e3 repository
|
|
41
|
+
* @param fields - Object mapping field names to DataRefs
|
|
42
|
+
* @param structure - The structure describing this tree node's shape
|
|
43
|
+
* @returns Hash of the written tree object
|
|
44
|
+
* @throws If structure is not a tree or encoding fails
|
|
45
|
+
*/
|
|
46
|
+
export declare function treeWrite(repoPath: string, fields: TreeObject, structure: Structure): Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Read and decode a dataset value from the object store.
|
|
49
|
+
*
|
|
50
|
+
* The .beast2 format includes type information in the header, so values
|
|
51
|
+
* can be decoded without knowing the schema in advance.
|
|
52
|
+
*
|
|
53
|
+
* @param repoPath - Path to .e3 repository
|
|
54
|
+
* @param hash - Hash of the dataset value
|
|
55
|
+
* @returns The decoded value and its type
|
|
56
|
+
* @throws If object not found or not a valid beast2 object
|
|
57
|
+
*/
|
|
58
|
+
export declare function datasetRead(repoPath: string, hash: string): Promise<{
|
|
59
|
+
type: EastType;
|
|
60
|
+
value: unknown;
|
|
61
|
+
}>;
|
|
62
|
+
/**
|
|
63
|
+
* Encode and write a dataset value to the object store.
|
|
64
|
+
*
|
|
65
|
+
* @param repoPath - Path to .e3 repository
|
|
66
|
+
* @param value - The value to encode
|
|
67
|
+
* @param type - The East type for encoding (EastType or EastTypeValue)
|
|
68
|
+
* @returns Hash of the written dataset value
|
|
69
|
+
*/
|
|
70
|
+
export declare function datasetWrite(repoPath: string, value: unknown, type: EastType | EastTypeValue): Promise<string>;
|
|
71
|
+
/**
|
|
72
|
+
* List field names at a tree path within a package's data tree.
|
|
73
|
+
*
|
|
74
|
+
* @param repoPath - Path to .e3 repository
|
|
75
|
+
* @param name - Package name
|
|
76
|
+
* @param version - Package version
|
|
77
|
+
* @param path - Path to the tree node
|
|
78
|
+
* @returns Array of field names at the path
|
|
79
|
+
* @throws If package not found, path invalid, or path points to a dataset
|
|
80
|
+
*/
|
|
81
|
+
export declare function packageListTree(repoPath: string, name: string, version: string, path: TreePath): Promise<string[]>;
|
|
82
|
+
/**
|
|
83
|
+
* Read and decode a dataset value at a path within a package's data tree.
|
|
84
|
+
*
|
|
85
|
+
* @param repoPath - Path to .e3 repository
|
|
86
|
+
* @param name - Package name
|
|
87
|
+
* @param version - Package version
|
|
88
|
+
* @param path - Path to the dataset
|
|
89
|
+
* @returns The decoded dataset value
|
|
90
|
+
* @throws If package not found, path invalid, or path points to a tree
|
|
91
|
+
*/
|
|
92
|
+
export declare function packageGetDataset(repoPath: string, name: string, version: string, path: TreePath): Promise<unknown>;
|
|
93
|
+
/**
|
|
94
|
+
* Update a dataset at a path within a workspace.
|
|
95
|
+
*
|
|
96
|
+
* This creates new tree objects along the path with structural sharing,
|
|
97
|
+
* then atomically updates the workspace root.
|
|
98
|
+
*
|
|
99
|
+
* @param repoPath - Path to .e3 repository
|
|
100
|
+
* @param ws - Workspace name
|
|
101
|
+
* @param treePath - Path to the dataset
|
|
102
|
+
* @param value - The new value to write
|
|
103
|
+
* @param type - The East type for encoding the value (EastType or EastTypeValue)
|
|
104
|
+
* @throws If workspace not deployed, path invalid, or path points to a tree
|
|
105
|
+
*/
|
|
106
|
+
export declare function workspaceSetDataset(repoPath: string, ws: string, treePath: TreePath, value: unknown, type: EastType | EastTypeValue): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* List field names at a tree path within a workspace's data tree.
|
|
109
|
+
*
|
|
110
|
+
* @param repoPath - Path to .e3 repository
|
|
111
|
+
* @param ws - Workspace name
|
|
112
|
+
* @param path - Path to the tree node
|
|
113
|
+
* @returns Array of field names at the path
|
|
114
|
+
* @throws If workspace not deployed, path invalid, or path points to a dataset
|
|
115
|
+
*/
|
|
116
|
+
export declare function workspaceListTree(repoPath: string, ws: string, treePath: TreePath): Promise<string[]>;
|
|
117
|
+
/**
|
|
118
|
+
* Read and decode a dataset value at a path within a workspace's data tree.
|
|
119
|
+
*
|
|
120
|
+
* @param repoPath - Path to .e3 repository
|
|
121
|
+
* @param ws - Workspace name
|
|
122
|
+
* @param path - Path to the dataset
|
|
123
|
+
* @returns The decoded dataset value
|
|
124
|
+
* @throws If workspace not deployed, path invalid, or path points to a tree
|
|
125
|
+
*/
|
|
126
|
+
export declare function workspaceGetDataset(repoPath: string, ws: string, treePath: TreePath): Promise<unknown>;
|
|
127
|
+
/**
|
|
128
|
+
* Get the hash of a dataset at a path within a workspace's data tree.
|
|
129
|
+
*
|
|
130
|
+
* Unlike workspaceGetDataset which decodes the value, this returns the raw
|
|
131
|
+
* hash reference. Useful for dataflow execution which operates on hashes.
|
|
132
|
+
*
|
|
133
|
+
* @param repoPath - Path to .e3 repository
|
|
134
|
+
* @param ws - Workspace name
|
|
135
|
+
* @param treePath - Path to the dataset
|
|
136
|
+
* @returns Object with ref type and hash (null for unassigned/null refs)
|
|
137
|
+
* @throws If workspace not deployed, path invalid, or path points to a tree
|
|
138
|
+
*/
|
|
139
|
+
export declare function workspaceGetDatasetHash(repoPath: string, ws: string, treePath: TreePath): Promise<{
|
|
140
|
+
refType: DataRef['type'];
|
|
141
|
+
hash: string | null;
|
|
142
|
+
}>;
|
|
143
|
+
/**
|
|
144
|
+
* Set a dataset at a path within a workspace using a pre-computed hash.
|
|
145
|
+
*
|
|
146
|
+
* Unlike workspaceSetDataset which encodes a value, this takes a hash
|
|
147
|
+
* directly. Useful for dataflow execution which already has the output hash.
|
|
148
|
+
*
|
|
149
|
+
* @param repoPath - Path to .e3 repository
|
|
150
|
+
* @param ws - Workspace name
|
|
151
|
+
* @param treePath - Path to the dataset
|
|
152
|
+
* @param valueHash - Hash of the dataset value already in the object store
|
|
153
|
+
* @throws If workspace not deployed, path invalid, or path points to a tree
|
|
154
|
+
*/
|
|
155
|
+
export declare function workspaceSetDatasetByHash(repoPath: string, ws: string, treePath: TreePath, valueHash: string): Promise<void>;
|
|
156
|
+
//# sourceMappingURL=trees.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trees.d.ts","sourceRoot":"","sources":["../../src/trees.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;GAYG;AAEH,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAsD,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAuB,MAAM,mBAAmB,CAAC;AAYzJ;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAyBjD;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,UAAU,CAAC,CAKrB;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAI7C;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,QAAQ,GAAG,aAAa,GAC7B,OAAO,CAAC,MAAM,CAAC,CAOjB;AAyFD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,MAAM,EAAE,CAAC,CAiCnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,OAAO,CAAC,CAoClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,QAAQ,GAAG,aAAa,GAC7B,OAAO,CAAC,IAAI,CAAC,CAiHf;AA2ED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CA8BnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,OAAO,CAAC,CAiClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CA2B5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA2Gf"}
|