@elaraai/e3 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 +31 -0
- package/README.md +73 -0
- package/dist/src/export.d.ts +31 -0
- package/dist/src/export.d.ts.map +1 -0
- package/dist/src/export.js +236 -0
- package/dist/src/export.js.map +1 -0
- package/dist/src/export.spec.d.ts +6 -0
- package/dist/src/export.spec.d.ts.map +1 -0
- package/dist/src/export.spec.js +176 -0
- package/dist/src/export.spec.js.map +1 -0
- package/dist/src/index.d.ts +69 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +30 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/input.d.ts +40 -0
- package/dist/src/input.d.ts.map +1 -0
- package/dist/src/input.js +49 -0
- package/dist/src/input.js.map +1 -0
- package/dist/src/package.d.ts +41 -0
- package/dist/src/package.d.ts.map +1 -0
- package/dist/src/package.js +111 -0
- package/dist/src/package.js.map +1 -0
- package/dist/src/sha256.d.ts +66 -0
- package/dist/src/sha256.d.ts.map +1 -0
- package/dist/src/sha256.js +106 -0
- package/dist/src/sha256.js.map +1 -0
- package/dist/src/sha256.spec.d.ts +6 -0
- package/dist/src/sha256.spec.d.ts.map +1 -0
- package/dist/src/sha256.spec.js +157 -0
- package/dist/src/sha256.spec.js.map +1 -0
- package/dist/src/task.d.ts +65 -0
- package/dist/src/task.d.ts.map +1 -0
- package/dist/src/task.js +192 -0
- package/dist/src/task.js.map +1 -0
- package/dist/src/types.d.ts +117 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,69 @@
|
|
|
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
|
+
* e3: TypeScript SDK for authoring e3 packages.
|
|
7
|
+
*
|
|
8
|
+
* This package provides a fluent API for defining e3 packages in TypeScript:
|
|
9
|
+
* - `e3.input()` - Define input datasets
|
|
10
|
+
* - `e3.task()` - Define tasks that transform datasets
|
|
11
|
+
* - `e3.package()` - Bundle definitions into a package
|
|
12
|
+
* - `e3.export()` - Export package to a .zip bundle
|
|
13
|
+
*
|
|
14
|
+
* Terminology:
|
|
15
|
+
* - **Dataset**: A location holding a value (leaf node in the data tree)
|
|
16
|
+
* - **Tree**: A location containing datasets or nested trees (branch node)
|
|
17
|
+
* - **Structure**: The shape of the data tree
|
|
18
|
+
* - **Task**: A transformation that reads input datasets and produces an output dataset
|
|
19
|
+
* - **Path**: An address pointing to a dataset or tree
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { StringType } from '@elaraai/east';
|
|
24
|
+
* import e3 from '@elaraai/e3';
|
|
25
|
+
*
|
|
26
|
+
* const input_name = e3.input('name', StringType, 'World');
|
|
27
|
+
*
|
|
28
|
+
* const say_hello = e3.task(
|
|
29
|
+
* 'say_hello',
|
|
30
|
+
* [input_name],
|
|
31
|
+
* ($, name) => str`Hello, ${name}!`
|
|
32
|
+
* );
|
|
33
|
+
*
|
|
34
|
+
* // Only need to pass the final task - dependencies are collected automatically
|
|
35
|
+
* const pkg = e3.package('hello_world', '1.0.0', say_hello);
|
|
36
|
+
*
|
|
37
|
+
* // Discoverable access to package contents
|
|
38
|
+
* pkg.datasets.inputs.name; // input dataset
|
|
39
|
+
* pkg.datasets.outputs.say_hello; // output dataset
|
|
40
|
+
* pkg.tasks.say_hello; // task definition
|
|
41
|
+
*
|
|
42
|
+
* await e3.export(pkg, 'package.zip');
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
import type { DatasetDef, DataTreeDef, DatasetsOf, MergeDatasets, PackageDef, PackageItem, TaskDef } from './types.js';
|
|
46
|
+
import { input } from './input.js';
|
|
47
|
+
import { task, customTask } from './task.js';
|
|
48
|
+
import { package_ } from './package.js';
|
|
49
|
+
import { export_ } from './export.js';
|
|
50
|
+
export type { DataTreeDef, DatasetDef, DatasetsOf, TaskDef, PackageDef, PackageItem, MergeDatasets, };
|
|
51
|
+
/**
|
|
52
|
+
* The e3 SDK namespace.
|
|
53
|
+
*
|
|
54
|
+
* Provides functions for authoring e3 packages in TypeScript.
|
|
55
|
+
*/
|
|
56
|
+
declare const e3: {
|
|
57
|
+
input: typeof input;
|
|
58
|
+
task: typeof task;
|
|
59
|
+
customTask: typeof customTask;
|
|
60
|
+
package: typeof package_;
|
|
61
|
+
export: typeof export_;
|
|
62
|
+
};
|
|
63
|
+
export default e3;
|
|
64
|
+
export { input, task, customTask, package_ as package, export_ as export };
|
|
65
|
+
export { inputsTree } from './input.js';
|
|
66
|
+
export { tasksTree } from './task.js';
|
|
67
|
+
export { sha256File, sha256Bytes, hashToPath } from './sha256.js';
|
|
68
|
+
export { addObject } from './export.js';
|
|
69
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,OAAO,EACR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,YAAY,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,WAAW,EACX,aAAa,GACd,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,EAAE;;;;;;CAMP,CAAC;AAEF,eAAe,EAAE,CAAC;AAGlB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,IAAI,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC;AAG3E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
import { input } from './input.js';
|
|
6
|
+
import { task, customTask } from './task.js';
|
|
7
|
+
import { package_ } from './package.js';
|
|
8
|
+
import { export_ } from './export.js';
|
|
9
|
+
/**
|
|
10
|
+
* The e3 SDK namespace.
|
|
11
|
+
*
|
|
12
|
+
* Provides functions for authoring e3 packages in TypeScript.
|
|
13
|
+
*/
|
|
14
|
+
const e3 = {
|
|
15
|
+
input,
|
|
16
|
+
task,
|
|
17
|
+
customTask,
|
|
18
|
+
package: package_,
|
|
19
|
+
export: export_,
|
|
20
|
+
};
|
|
21
|
+
export default e3;
|
|
22
|
+
// Also export individual functions for tree-shaking
|
|
23
|
+
export { input, task, customTask, package_ as package, export_ as export };
|
|
24
|
+
// Singleton tree definitions
|
|
25
|
+
export { inputsTree } from './input.js';
|
|
26
|
+
export { tasksTree } from './task.js';
|
|
27
|
+
// Utility exports
|
|
28
|
+
export { sha256File, sha256Bytes, hashToPath } from './sha256.js';
|
|
29
|
+
export { addObject } from './export.js';
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoDH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAYtC;;;;GAIG;AACH,MAAM,EAAE,GAAG;IACT,KAAK;IACL,IAAI;IACJ,UAAU;IACV,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,OAAO;CAChB,CAAC;AAEF,eAAe,EAAE,CAAC;AAElB,oDAAoD;AACpD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,IAAI,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC;AAE3E,6BAA6B;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
* Input dataset definitions for e3 packages.
|
|
7
|
+
*/
|
|
8
|
+
import type { EastType, ValueTypeOf } from '@elaraai/east';
|
|
9
|
+
import { variant } from '@elaraai/east';
|
|
10
|
+
import type { DatasetDef, DataTreeDef } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Singleton datatree definition for `.inputs`.
|
|
13
|
+
*
|
|
14
|
+
* All input datasets are children of this datatree.
|
|
15
|
+
*/
|
|
16
|
+
export declare const inputsTree: DataTreeDef;
|
|
17
|
+
/**
|
|
18
|
+
* Defines an input dataset.
|
|
19
|
+
*
|
|
20
|
+
* Creates a dataset at `.inputs.${name}` in the workspace.
|
|
21
|
+
*
|
|
22
|
+
* @typeParam T - The East type of the input value
|
|
23
|
+
* @param name - Dataset name (used as path segment in the tree)
|
|
24
|
+
* @param type - East type of the input value
|
|
25
|
+
* @param defaultValue - Optional default value
|
|
26
|
+
* @returns A DatasetDef that can be used in dataflows and packages
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { StringType, IntegerType } from '@elaraai/east';
|
|
31
|
+
*
|
|
32
|
+
* // Input with default
|
|
33
|
+
* const name = input('name', StringType, 'World');
|
|
34
|
+
*
|
|
35
|
+
* // Input without default
|
|
36
|
+
* const count = input('count', IntegerType);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function input<Name extends string, T extends EastType>(name: Name, type: T, defaultValue?: ValueTypeOf<T>): DatasetDef<T, [variant<"field", "inputs">, variant<"field", Name>]>;
|
|
40
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/input.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,WAKxB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,KAAK,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,SAAS,QAAQ,EAC3D,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,CAAC,EACP,YAAY,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAC5B,UAAU,CAAC,CAAC,EAAE,CAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAE,CAAC,CASvE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
import { variant } from '@elaraai/east';
|
|
6
|
+
/**
|
|
7
|
+
* Singleton datatree definition for `.inputs`.
|
|
8
|
+
*
|
|
9
|
+
* All input datasets are children of this datatree.
|
|
10
|
+
*/
|
|
11
|
+
export const inputsTree = {
|
|
12
|
+
kind: 'datatree',
|
|
13
|
+
name: 'inputs',
|
|
14
|
+
path: [variant('field', 'inputs')],
|
|
15
|
+
deps: new Set(),
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Defines an input dataset.
|
|
19
|
+
*
|
|
20
|
+
* Creates a dataset at `.inputs.${name}` in the workspace.
|
|
21
|
+
*
|
|
22
|
+
* @typeParam T - The East type of the input value
|
|
23
|
+
* @param name - Dataset name (used as path segment in the tree)
|
|
24
|
+
* @param type - East type of the input value
|
|
25
|
+
* @param defaultValue - Optional default value
|
|
26
|
+
* @returns A DatasetDef that can be used in dataflows and packages
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { StringType, IntegerType } from '@elaraai/east';
|
|
31
|
+
*
|
|
32
|
+
* // Input with default
|
|
33
|
+
* const name = input('name', StringType, 'World');
|
|
34
|
+
*
|
|
35
|
+
* // Input without default
|
|
36
|
+
* const count = input('count', IntegerType);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function input(name, type, defaultValue) {
|
|
40
|
+
return {
|
|
41
|
+
kind: 'dataset',
|
|
42
|
+
name,
|
|
43
|
+
path: [variant('field', 'inputs'), variant('field', name)],
|
|
44
|
+
type,
|
|
45
|
+
default: defaultValue,
|
|
46
|
+
deps: new Set([...inputsTree.deps, inputsTree]),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/input.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAgB;IACrC,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClC,IAAI,EAAE,IAAI,GAAG,EAAE;CAChB,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,KAAK,CACnB,IAAU,EACV,IAAO,EACP,YAA6B;IAE7B,OAAO;QACL,IAAI,EAAE,SAAS;QACf,IAAI;QACJ,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC1D,IAAI;QACJ,OAAO,EAAE,YAAY;QACrB,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;KAChD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
* Package definitions for e3.
|
|
7
|
+
*/
|
|
8
|
+
import type { MergeDatasets, PackageDef, PackageItem } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Creates a package definition from items.
|
|
11
|
+
*
|
|
12
|
+
* Automatically collects all dependencies from the provided items.
|
|
13
|
+
* You only need to pass the "top-level" items - all inputs, intermediate
|
|
14
|
+
* tasks, and datasets they depend on are included automatically.
|
|
15
|
+
*
|
|
16
|
+
* Organizes items into a discoverable structure:
|
|
17
|
+
* - `pkg.datasets.inputs.*` - Input datasets
|
|
18
|
+
* - `pkg.datasets.outputs.*` - Output datasets
|
|
19
|
+
* - `pkg.tasks.*` - Tasks
|
|
20
|
+
*
|
|
21
|
+
* @param name - Package name
|
|
22
|
+
* @param version - Package version
|
|
23
|
+
* @param items - Items to include (datasets, tasks)
|
|
24
|
+
* @returns A PackageDef with typed access to contents
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const input_name = e3.input('name', StringType, 'World');
|
|
29
|
+
* const say_hello = e3.task('say_hello', [input_name], ...);
|
|
30
|
+
*
|
|
31
|
+
* // Only need to pass the final task - input_name is included automatically
|
|
32
|
+
* const pkg = e3.package('hello_world', '1.0.0', say_hello);
|
|
33
|
+
*
|
|
34
|
+
* // Typed access to contents
|
|
35
|
+
* const nameInput = pkg.datasets.inputs.name;
|
|
36
|
+
* const helloOutput = pkg.datasets.outputs.say_hello;
|
|
37
|
+
* const helloTask = pkg.tasks.say_hello;
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function package_<TItems extends (PackageItem | PackageDef<any>)[]>(name: string, version: string, ...items: TItems): PackageDef<MergeDatasets<TItems>>;
|
|
41
|
+
//# sourceMappingURL=package.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/package.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,WAAW,EAEZ,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,CAAC,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EACvE,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,GAAG,KAAK,EAAE,MAAM,GACf,UAAU,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CA6EnC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
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 package definition from items.
|
|
7
|
+
*
|
|
8
|
+
* Automatically collects all dependencies from the provided items.
|
|
9
|
+
* You only need to pass the "top-level" items - all inputs, intermediate
|
|
10
|
+
* tasks, and datasets they depend on are included automatically.
|
|
11
|
+
*
|
|
12
|
+
* Organizes items into a discoverable structure:
|
|
13
|
+
* - `pkg.datasets.inputs.*` - Input datasets
|
|
14
|
+
* - `pkg.datasets.outputs.*` - Output datasets
|
|
15
|
+
* - `pkg.tasks.*` - Tasks
|
|
16
|
+
*
|
|
17
|
+
* @param name - Package name
|
|
18
|
+
* @param version - Package version
|
|
19
|
+
* @param items - Items to include (datasets, tasks)
|
|
20
|
+
* @returns A PackageDef with typed access to contents
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const input_name = e3.input('name', StringType, 'World');
|
|
25
|
+
* const say_hello = e3.task('say_hello', [input_name], ...);
|
|
26
|
+
*
|
|
27
|
+
* // Only need to pass the final task - input_name is included automatically
|
|
28
|
+
* const pkg = e3.package('hello_world', '1.0.0', say_hello);
|
|
29
|
+
*
|
|
30
|
+
* // Typed access to contents
|
|
31
|
+
* const nameInput = pkg.datasets.inputs.name;
|
|
32
|
+
* const helloOutput = pkg.datasets.outputs.say_hello;
|
|
33
|
+
* const helloTask = pkg.tasks.say_hello;
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function package_(name, version, ...items) {
|
|
37
|
+
// Recursively collect all items and their transitive dependencies
|
|
38
|
+
const all_items = new Set();
|
|
39
|
+
const visited = new Set();
|
|
40
|
+
function collect(item) {
|
|
41
|
+
if (visited.has(item))
|
|
42
|
+
return;
|
|
43
|
+
visited.add(item);
|
|
44
|
+
// First collect all dependencies recursively
|
|
45
|
+
for (const dep of item.deps) {
|
|
46
|
+
collect(dep);
|
|
47
|
+
}
|
|
48
|
+
// Then add this item (ensures topological order)
|
|
49
|
+
all_items.add(item);
|
|
50
|
+
}
|
|
51
|
+
for (const item of items) {
|
|
52
|
+
if (item.kind === "package") {
|
|
53
|
+
for (const dep of item.contents) {
|
|
54
|
+
all_items.add(dep);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
collect(item);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const datasets = {};
|
|
62
|
+
const tasks = {};
|
|
63
|
+
// all_items is in topological order by construction
|
|
64
|
+
for (const item of all_items) {
|
|
65
|
+
if (item.kind === 'datatree') {
|
|
66
|
+
let current = datasets;
|
|
67
|
+
for (let i = 0; i < item.path.length - 1; i++) { // TODO should this path be the parent path?
|
|
68
|
+
const segment = item.path[i];
|
|
69
|
+
if (segment.type === 'field') {
|
|
70
|
+
current = current[segment.value];
|
|
71
|
+
if (current === undefined) {
|
|
72
|
+
throw new Error(`Parent tree not found in package(): ${segment.value}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
throw new Error(`Unsupported path segment type in package(): ${segment.type}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// the only tree type is struct for now
|
|
80
|
+
current[item.name] = {};
|
|
81
|
+
}
|
|
82
|
+
else if (item.kind === 'dataset') {
|
|
83
|
+
let current = datasets;
|
|
84
|
+
for (let i = 0; i < item.path.length - 1; i++) { // TODO should this path be the parent path?
|
|
85
|
+
const segment = item.path[i];
|
|
86
|
+
if (segment.type === 'field') {
|
|
87
|
+
current = current[segment.value];
|
|
88
|
+
if (current === undefined) {
|
|
89
|
+
throw new Error(`Parent tree not found in package(): ${segment.value}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
throw new Error(`Unsupported path segment type in package(): ${segment.type}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
current[item.name] = item;
|
|
97
|
+
}
|
|
98
|
+
else if (item.kind === 'task') {
|
|
99
|
+
// TODO - check task inputs and output exist with correct types?
|
|
100
|
+
tasks[item.name] = item;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
kind: 'package',
|
|
105
|
+
name,
|
|
106
|
+
version,
|
|
107
|
+
datasets: datasets,
|
|
108
|
+
contents: [...all_items],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=package.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package.js","sourceRoot":"","sources":["../../src/package.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAY,EACZ,OAAe,EACf,GAAG,KAAa;IAEhB,kEAAkE;IAClE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAe,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IAEvC,SAAS,OAAO,CAAC,IAAiB;QAChC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAC9B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAElB,6CAA6C;QAC7C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QAED,iDAAiD;QACjD,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,oDAAoD;IACpD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,IAAI,OAAO,GAAG,QAAQ,CAAC;YACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,4CAA4C;gBAC3F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC7B,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC7B,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBACjC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;wBAC1B,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;oBAC1E,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CAAC,+CAA+C,OAAO,CAAC,IAAoB,EAAE,CAAC,CAAC;gBACjG,CAAC;YACH,CAAC;YAED,uCAAuC;YACvC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1B,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,OAAO,GAAG,QAAQ,CAAC;YACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,4CAA4C;gBAC3F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC7B,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC7B,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBACjC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;wBAC1B,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;oBAC1E,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CAAC,+CAA+C,OAAO,CAAC,IAAoB,EAAE,CAAC,CAAC;gBACjG,CAAC;YACH,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAC5B,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAChC,gEAAgE;YAChE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,SAAS;QACf,IAAI;QACJ,OAAO;QACP,QAAQ,EAAE,QAAe;QACzB,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAC;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
* Computes the SHA256 hash of a file.
|
|
7
|
+
*
|
|
8
|
+
* Reads the file in streaming mode to handle large files efficiently
|
|
9
|
+
* without loading the entire contents into memory.
|
|
10
|
+
*
|
|
11
|
+
* @param path - Absolute or relative path to the file
|
|
12
|
+
* @returns The SHA256 hash as a 64-character lowercase hex string
|
|
13
|
+
*
|
|
14
|
+
* @throws {Error} When the file does not exist or cannot be read
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* - Uses Node.js crypto module for hashing
|
|
18
|
+
* - Streams file contents to avoid memory pressure on large files
|
|
19
|
+
* - Returns lowercase hex encoding (64 characters for SHA256)
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { sha256File } from '@elaraai/e3';
|
|
24
|
+
*
|
|
25
|
+
* const hash = await sha256File('./myfile.txt');
|
|
26
|
+
* // hash: "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function sha256File(path: string): Promise<string>;
|
|
30
|
+
/**
|
|
31
|
+
* Computes the SHA256 hash of a byte array.
|
|
32
|
+
*
|
|
33
|
+
* @param data - The bytes to hash
|
|
34
|
+
* @returns The SHA256 hash as a 64-character lowercase hex string
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { sha256Bytes } from '@elaraai/e3';
|
|
39
|
+
*
|
|
40
|
+
* const data = new TextEncoder().encode('hello world');
|
|
41
|
+
* const hash = sha256Bytes(data);
|
|
42
|
+
* // hash: "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function sha256Bytes(data: Uint8Array): string;
|
|
46
|
+
/**
|
|
47
|
+
* Converts a SHA256 hex string to an object store path.
|
|
48
|
+
*
|
|
49
|
+
* The path uses the first 2 characters as a directory prefix for sharding,
|
|
50
|
+
* followed by the remaining 62 characters as the filename.
|
|
51
|
+
*
|
|
52
|
+
* @param hash - A 64-character lowercase hex SHA256 hash
|
|
53
|
+
* @returns Path of the form "objects/ab/cdef1234..."
|
|
54
|
+
*
|
|
55
|
+
* @throws {Error} When the hash is not a valid 64-character hex string
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { hashToPath } from '@elaraai/e3';
|
|
60
|
+
*
|
|
61
|
+
* const path = hashToPath('b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9');
|
|
62
|
+
* // path: "objects/b9/4d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function hashToPath(hash: string): string;
|
|
66
|
+
//# sourceMappingURL=sha256.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.d.ts","sourceRoot":"","sources":["../../src/sha256.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B9D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEpD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C"}
|
|
@@ -0,0 +1,106 @@
|
|
|
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
|
+
* SHA256 hashing utilities for e3.
|
|
7
|
+
*/
|
|
8
|
+
import { createHash } from 'node:crypto';
|
|
9
|
+
import { createReadStream } from 'node:fs';
|
|
10
|
+
import { stat } from 'node:fs/promises';
|
|
11
|
+
/**
|
|
12
|
+
* Computes the SHA256 hash of a file.
|
|
13
|
+
*
|
|
14
|
+
* Reads the file in streaming mode to handle large files efficiently
|
|
15
|
+
* without loading the entire contents into memory.
|
|
16
|
+
*
|
|
17
|
+
* @param path - Absolute or relative path to the file
|
|
18
|
+
* @returns The SHA256 hash as a 64-character lowercase hex string
|
|
19
|
+
*
|
|
20
|
+
* @throws {Error} When the file does not exist or cannot be read
|
|
21
|
+
*
|
|
22
|
+
* @remarks
|
|
23
|
+
* - Uses Node.js crypto module for hashing
|
|
24
|
+
* - Streams file contents to avoid memory pressure on large files
|
|
25
|
+
* - Returns lowercase hex encoding (64 characters for SHA256)
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { sha256File } from '@elaraai/e3';
|
|
30
|
+
*
|
|
31
|
+
* const hash = await sha256File('./myfile.txt');
|
|
32
|
+
* // hash: "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export async function sha256File(path) {
|
|
36
|
+
// Check file exists first for a clearer error message
|
|
37
|
+
try {
|
|
38
|
+
const stats = await stat(path);
|
|
39
|
+
if (!stats.isFile()) {
|
|
40
|
+
throw new Error(`Not a file: ${path}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {
|
|
45
|
+
throw new Error(`File not found: ${path}`);
|
|
46
|
+
}
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const hash = createHash('sha256');
|
|
51
|
+
const stream = createReadStream(path);
|
|
52
|
+
stream.on('data', (chunk) => {
|
|
53
|
+
hash.update(chunk);
|
|
54
|
+
});
|
|
55
|
+
stream.on('end', () => {
|
|
56
|
+
resolve(hash.digest('hex'));
|
|
57
|
+
});
|
|
58
|
+
stream.on('error', (err) => {
|
|
59
|
+
reject(err);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Computes the SHA256 hash of a byte array.
|
|
65
|
+
*
|
|
66
|
+
* @param data - The bytes to hash
|
|
67
|
+
* @returns The SHA256 hash as a 64-character lowercase hex string
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { sha256Bytes } from '@elaraai/e3';
|
|
72
|
+
*
|
|
73
|
+
* const data = new TextEncoder().encode('hello world');
|
|
74
|
+
* const hash = sha256Bytes(data);
|
|
75
|
+
* // hash: "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export function sha256Bytes(data) {
|
|
79
|
+
return createHash('sha256').update(data).digest('hex');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Converts a SHA256 hex string to an object store path.
|
|
83
|
+
*
|
|
84
|
+
* The path uses the first 2 characters as a directory prefix for sharding,
|
|
85
|
+
* followed by the remaining 62 characters as the filename.
|
|
86
|
+
*
|
|
87
|
+
* @param hash - A 64-character lowercase hex SHA256 hash
|
|
88
|
+
* @returns Path of the form "objects/ab/cdef1234..."
|
|
89
|
+
*
|
|
90
|
+
* @throws {Error} When the hash is not a valid 64-character hex string
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* import { hashToPath } from '@elaraai/e3';
|
|
95
|
+
*
|
|
96
|
+
* const path = hashToPath('b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9');
|
|
97
|
+
* // path: "objects/b9/4d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export function hashToPath(hash) {
|
|
101
|
+
if (!/^[0-9a-f]{64}$/.test(hash)) {
|
|
102
|
+
throw new Error(`Invalid SHA256 hash: expected 64 lowercase hex characters, got "${hash}"`);
|
|
103
|
+
}
|
|
104
|
+
return `objects/${hash.slice(0, 2)}/${hash.slice(2)}`;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=sha256.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.js","sourceRoot":"","sources":["../../src/sha256.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,sDAAsD;IACtD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAEtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACpB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,WAAW,CAAC,IAAgB;IAC1C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,mEAAmE,IAAI,GAAG,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,WAAW,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.spec.d.ts","sourceRoot":"","sources":["../../src/sha256.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|