@elaraai/east-node-cli 1.0.68 → 1.0.70
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 +66 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +82 -0
- package/dist/cli.js.map +1 -1
- package/dist/export-functions.d.ts +29 -0
- package/dist/export-functions.d.ts.map +1 -0
- package/dist/export-functions.js +71 -0
- package/dist/export-functions.js.map +1 -0
- package/dist/export-functions.spec.d.ts +6 -0
- package/dist/export-functions.spec.d.ts.map +1 -0
- package/dist/export-functions.spec.js +104 -0
- package/dist/export-functions.spec.js.map +1 -0
- package/dist/loader.d.ts +19 -3
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +66 -8
- package/dist/loader.js.map +1 -1
- package/dist/loader.spec.js +47 -1
- package/dist/loader.spec.js.map +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +22 -3
- package/dist/runner.js.map +1 -1
- package/dist/runner.spec.js +69 -1
- package/dist/runner.spec.js.map +1 -1
- package/dist/transpile.d.ts +58 -0
- package/dist/transpile.d.ts.map +1 -0
- package/dist/transpile.js +129 -0
- package/dist/transpile.js.map +1 -0
- package/dist/transpile.spec.d.ts +6 -0
- package/dist/transpile.spec.d.ts.map +1 -0
- package/dist/transpile.spec.js +110 -0
- package/dist/transpile.spec.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -57,6 +57,35 @@ east-node version
|
|
|
57
57
|
east-node version -p @elaraai/east-node-std -p @elaraai/east-node-io
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
### Transpiling IR to TypeScript
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Print an IR program as East.function builder source
|
|
64
|
+
east-node transpile ./program.beast2 -o program.ts
|
|
65
|
+
|
|
66
|
+
# Every IR file in a directory, plus the IR each printed module builds
|
|
67
|
+
# back — the round-trip check
|
|
68
|
+
east-node transpile ./ir/ -o ./ts/ --rebuild ./rebuilt/
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The printed module imports `@elaraai/east` and rebuilds the same IR
|
|
72
|
+
(equal under `east-c ir normalize`): the `$`-forms for statements,
|
|
73
|
+
expression methods and `East.value(..., T)` constructions for values.
|
|
74
|
+
Builtins the TypeScript surface has no spelling for print through
|
|
75
|
+
`East.builtin(...)`. `east-py transpile` is the python twin; the two
|
|
76
|
+
printers and the cross-language sweep are described in
|
|
77
|
+
`docs/conventions/EAST_CODEGEN.md`.
|
|
78
|
+
|
|
79
|
+
### Exporting functions for another language
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Write a module's `eastFunctions` export as a function manifest that a python
|
|
83
|
+
# package (or another TypeScript package) imports with East.import_function /
|
|
84
|
+
# East.importFunction; -p names the platform packages implementing any
|
|
85
|
+
# platform calls the functions make
|
|
86
|
+
east-node export-functions dist/pricing.js -o pricing.functions.beast2 -p @elaraai/east-node-std
|
|
87
|
+
```
|
|
88
|
+
|
|
60
89
|
## CLI Reference
|
|
61
90
|
|
|
62
91
|
### `east-node run`
|
|
@@ -77,6 +106,43 @@ Options:
|
|
|
77
106
|
-h, --help Display help
|
|
78
107
|
```
|
|
79
108
|
|
|
109
|
+
### `east-node transpile`
|
|
110
|
+
|
|
111
|
+
Print an East IR program as TypeScript `East.function` builder source.
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
east-node transpile <input> [options]
|
|
115
|
+
|
|
116
|
+
Arguments:
|
|
117
|
+
input Path to an IR file (.beast2, .beast, .east, or .json), or a directory of them
|
|
118
|
+
|
|
119
|
+
Options:
|
|
120
|
+
-o, --output <path> Write the module here (a directory when <input> is one; default: stdout)
|
|
121
|
+
--name <name> The module-level export bound to the rebuilt function (default: main)
|
|
122
|
+
--import-from <specifier> The module the printed source imports East from (default: @elaraai/east)
|
|
123
|
+
--rebuild <path> Import the printed module and write the IR it builds here
|
|
124
|
+
(.beast2 or .json; a directory in directory mode)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `east-node export-functions`
|
|
128
|
+
|
|
129
|
+
Write a module's `eastFunctions` export (name → `East.function` result) as a function manifest.
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
east-node export-functions <module> -o <file> [options]
|
|
133
|
+
|
|
134
|
+
Arguments:
|
|
135
|
+
module Path to the built module exporting `eastFunctions`
|
|
136
|
+
|
|
137
|
+
Options:
|
|
138
|
+
-o, --output <file> The manifest to write (.beast2)
|
|
139
|
+
-p, --package <package...> Platform packages implementing the functions' platform calls
|
|
140
|
+
(every dependency must be provided by one; recorded as its provider)
|
|
141
|
+
--name <name> The package name importers use (default: the module file's stem)
|
|
142
|
+
--package-version <version> The version recorded in the manifest (default: 0.0.0)
|
|
143
|
+
--only <name...> Export only these functions of `eastFunctions` (default: all)
|
|
144
|
+
```
|
|
145
|
+
|
|
80
146
|
### `east-node version`
|
|
81
147
|
|
|
82
148
|
Show version information.
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA2PH,wBAAgB,IAAI,IAAI,IAAI,CAwD3B"}
|
package/dist/cli.js
CHANGED
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
import { Command } from 'commander';
|
|
6
|
+
import { writeFileSync } from 'node:fs';
|
|
6
7
|
import { createRequire } from 'module';
|
|
7
8
|
import { EastError } from '@elaraai/east/internal';
|
|
8
9
|
import { loadPlatforms, loadPlatformWithMetadata } from './loader.js';
|
|
9
10
|
import { runProgram } from './runner.js';
|
|
10
11
|
import { writeSnapshot, readSnapshot } from './snapshot.js';
|
|
12
|
+
import { encodeRebuilt, isDirectory, transpile, transpileDir } from './transpile.js';
|
|
13
|
+
import { exportFunctionsFromModule } from './export-functions.js';
|
|
14
|
+
import { East } from '@elaraai/east';
|
|
11
15
|
const require = createRequire(import.meta.url);
|
|
12
16
|
const pkg = require('../package.json');
|
|
13
17
|
/** Parses the streaming-execution flags into runner options. */
|
|
@@ -111,6 +115,65 @@ async function cmdRun(irFile, options) {
|
|
|
111
115
|
: (e.stack ?? `Error: ${e.message ?? String(err)}`));
|
|
112
116
|
}
|
|
113
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* `east-node transpile` (#628): print an IR file — or every IR file in a
|
|
120
|
+
* directory — as the TypeScript `East.function` builder surface. With
|
|
121
|
+
* `--rebuild`, the printed module is imported and the IR it builds is
|
|
122
|
+
* written too: the round-trip check, and the TypeScript leg of the
|
|
123
|
+
* cross-language conformance sweep.
|
|
124
|
+
*/
|
|
125
|
+
async function cmdTranspile(input, options) {
|
|
126
|
+
try {
|
|
127
|
+
const common = {};
|
|
128
|
+
if (options.name !== undefined)
|
|
129
|
+
common.name = options.name;
|
|
130
|
+
if (options.importFrom !== undefined)
|
|
131
|
+
common.importFrom = options.importFrom;
|
|
132
|
+
if (isDirectory(input)) {
|
|
133
|
+
if (!options.output) {
|
|
134
|
+
return fail('Error: transpiling a directory needs -o <directory> for the modules');
|
|
135
|
+
}
|
|
136
|
+
const stems = await transpileDir(input, options.output, options.rebuild !== undefined ? { ...common, rebuildDir: options.rebuild } : common);
|
|
137
|
+
console.error(`Transpiled ${stems.length} IR file(s) to ${options.output}` +
|
|
138
|
+
(options.rebuild ? `, rebuilt to ${options.rebuild}` : ''));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const { source, rebuilt } = await transpile(input, { ...common, rebuild: options.rebuild !== undefined });
|
|
142
|
+
if (options.output) {
|
|
143
|
+
writeFileSync(options.output, source, 'utf-8');
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
process.stdout.write(source);
|
|
147
|
+
}
|
|
148
|
+
if (options.rebuild) {
|
|
149
|
+
writeFileSync(options.rebuild, encodeRebuilt(rebuilt, options.rebuild));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
return fail(`Error: ${err.message}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* `east-node export-functions` (#628): write a module's `eastFunctions` as a
|
|
158
|
+
* function manifest other packages — in TypeScript or python — import.
|
|
159
|
+
*/
|
|
160
|
+
async function cmdExportFunctions(modulePath, options) {
|
|
161
|
+
try {
|
|
162
|
+
const opts = { packages: options.package ?? [] };
|
|
163
|
+
if (options.name !== undefined)
|
|
164
|
+
opts.name = options.name;
|
|
165
|
+
if (options.packageVersion !== undefined)
|
|
166
|
+
opts.version = options.packageVersion;
|
|
167
|
+
if (options.only !== undefined)
|
|
168
|
+
opts.only = options.only;
|
|
169
|
+
const manifest = await exportFunctionsFromModule(modulePath, opts);
|
|
170
|
+
writeFileSync(options.output, East.encodeFunctionManifest(manifest));
|
|
171
|
+
console.error(`Exported ${manifest.functions.length} function(s) of ${manifest.package}@${manifest.version} to ${options.output}`);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
return fail(`Error: ${err.message}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
114
177
|
async function cmdVersion(options) {
|
|
115
178
|
console.log(`${pkg.name} ${pkg.version}`);
|
|
116
179
|
// Try to get east version
|
|
@@ -156,6 +219,25 @@ export function main() {
|
|
|
156
219
|
.option('--stream <index>', 'Feed the given -i input (0-based) lazily, segment-by-segment')
|
|
157
220
|
.option('--lazy-inputs <bytes>', 'Open indexed collection inputs at or above this size lazily (0 disables; default 64 MiB)')
|
|
158
221
|
.action(cmdRun);
|
|
222
|
+
program
|
|
223
|
+
.command('transpile')
|
|
224
|
+
.description('Print an East IR program as TypeScript East.function builder source')
|
|
225
|
+
.argument('<input>', 'Path to an IR file (.beast2, .beast, .east, or .json), or a directory of them')
|
|
226
|
+
.option('-o, --output <path>', 'Write the module here (a directory when <input> is one; default: stdout)')
|
|
227
|
+
.option('--name <name>', 'The module-level export bound to the rebuilt function (default: main)')
|
|
228
|
+
.option('--import-from <specifier>', 'The module the printed source imports East from (default: @elaraai/east)')
|
|
229
|
+
.option('--rebuild <path>', 'Import the printed module and write the IR it builds here (.beast2 or .json; a directory in directory mode)')
|
|
230
|
+
.action(cmdTranspile);
|
|
231
|
+
program
|
|
232
|
+
.command('export-functions')
|
|
233
|
+
.description("Write a module's `eastFunctions` export as a function manifest other packages (TypeScript or python) import")
|
|
234
|
+
.argument('<module>', 'Path to the built module exporting `eastFunctions` (name -> East.function)')
|
|
235
|
+
.requiredOption('-o, --output <file>', 'The manifest to write (.beast2)')
|
|
236
|
+
.option('-p, --package <package...>', "Platform packages implementing the functions' platform calls (each dependency must be provided by one)")
|
|
237
|
+
.option('--name <name>', "The package name importers use (default: the module file's stem)")
|
|
238
|
+
.option('--package-version <version>', 'The version recorded in the manifest (default: 0.0.0)')
|
|
239
|
+
.option('--only <name...>', 'Export only these functions of `eastFunctions` (default: all)')
|
|
240
|
+
.action(cmdExportFunctions);
|
|
159
241
|
program
|
|
160
242
|
.command('version')
|
|
161
243
|
.description('Show version information')
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
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 { type FunctionManifest } from '@elaraai/east';
|
|
6
|
+
/** Options for {@link exportFunctionsFromModule}. */
|
|
7
|
+
export interface ExportFunctionsOptions {
|
|
8
|
+
/** The package name importers use (default: the module file's stem). */
|
|
9
|
+
name?: string;
|
|
10
|
+
/** The version recorded in the manifest (default `0.0.0`). */
|
|
11
|
+
version?: string;
|
|
12
|
+
/** Platform packages implementing the functions' platform calls. */
|
|
13
|
+
packages?: string[];
|
|
14
|
+
/** Export only these functions of `eastFunctions` (default: all); a name it does not export is an error naming what it does. */
|
|
15
|
+
only?: string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Loads a module and builds the manifest of its `eastFunctions` export
|
|
19
|
+
* (name → `East.function` result).
|
|
20
|
+
*
|
|
21
|
+
* @param modulePath - Path to the module (a built `.js` / `.mjs`)
|
|
22
|
+
* @param options - Package name, version, the providing platform packages, and the functions to export
|
|
23
|
+
* @returns The manifest value
|
|
24
|
+
* @throws When the module has no `eastFunctions` object, a function in
|
|
25
|
+
* `only` is not exported, a function is not a closed value, or a platform
|
|
26
|
+
* dependency has no providing package
|
|
27
|
+
*/
|
|
28
|
+
export declare function exportFunctionsFromModule(modulePath: string, options?: ExportFunctionsOptions): Promise<FunctionManifest>;
|
|
29
|
+
//# sourceMappingURL=export-functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-functions.d.ts","sourceRoot":"","sources":["../src/export-functions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH,OAAO,EAAQ,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAG5D,qDAAqD;AACrD,MAAM,WAAW,sBAAsB;IACnC,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,gIAAgI;IAChI,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoCnI"}
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
* `east-node export-functions` (#628): a module's `eastFunctions` export
|
|
7
|
+
* written as a function manifest that other packages — in TypeScript or
|
|
8
|
+
* python — import with `East.importFunction` / `East.import_function`.
|
|
9
|
+
* The twin of `east-py export-functions`.
|
|
10
|
+
*
|
|
11
|
+
* Every platform function the exported functions call must be implemented
|
|
12
|
+
* by one of the `-p` platform packages, which is recorded as the
|
|
13
|
+
* dependency's provider; a dependency no package provides is an error
|
|
14
|
+
* naming it, so an importer's runner can be checked at its own build.
|
|
15
|
+
* `only` narrows the export to the named functions — what an importer
|
|
16
|
+
* actually uses — so a sibling function's platform call never fails an
|
|
17
|
+
* export that does not need it.
|
|
18
|
+
*/
|
|
19
|
+
import { basename, extname, resolve } from 'node:path';
|
|
20
|
+
import { pathToFileURL } from 'node:url';
|
|
21
|
+
import { East } from '@elaraai/east';
|
|
22
|
+
import { loadPlatform } from './loader.js';
|
|
23
|
+
/**
|
|
24
|
+
* Loads a module and builds the manifest of its `eastFunctions` export
|
|
25
|
+
* (name → `East.function` result).
|
|
26
|
+
*
|
|
27
|
+
* @param modulePath - Path to the module (a built `.js` / `.mjs`)
|
|
28
|
+
* @param options - Package name, version, the providing platform packages, and the functions to export
|
|
29
|
+
* @returns The manifest value
|
|
30
|
+
* @throws When the module has no `eastFunctions` object, a function in
|
|
31
|
+
* `only` is not exported, a function is not a closed value, or a platform
|
|
32
|
+
* dependency has no providing package
|
|
33
|
+
*/
|
|
34
|
+
export async function exportFunctionsFromModule(modulePath, options = {}) {
|
|
35
|
+
const path = resolve(modulePath);
|
|
36
|
+
const mod = await import(pathToFileURL(path).href);
|
|
37
|
+
const exported = mod.eastFunctions;
|
|
38
|
+
if (exported === null || typeof exported !== 'object') {
|
|
39
|
+
throw new Error(`${modulePath} exports no \`eastFunctions\` object (name -> East.function result)`);
|
|
40
|
+
}
|
|
41
|
+
let functions = exported;
|
|
42
|
+
if (options.only !== undefined) {
|
|
43
|
+
const missing = options.only.filter(name => !(name in functions));
|
|
44
|
+
if (missing.length > 0) {
|
|
45
|
+
throw new Error(`${modulePath} exports no function${missing.length === 1 ? '' : 's'} ${missing.map(n => JSON.stringify(n)).join(', ')} — ` +
|
|
46
|
+
`its eastFunctions are ${Object.keys(functions).join(', ') || '(none)'}`);
|
|
47
|
+
}
|
|
48
|
+
functions = Object.fromEntries(options.only.map(name => [name, exported[name]]));
|
|
49
|
+
}
|
|
50
|
+
const providers = {};
|
|
51
|
+
for (const pkg of options.packages ?? []) {
|
|
52
|
+
for (const fn of await loadPlatform(pkg)) {
|
|
53
|
+
if (!(fn.name in providers))
|
|
54
|
+
providers[fn.name] = pkg;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const missing = new Set();
|
|
58
|
+
for (const fn of Object.values(functions)) {
|
|
59
|
+
for (const dep of East.platformDependencies(fn)) {
|
|
60
|
+
if (!(dep.name in providers))
|
|
61
|
+
missing.add(dep.name);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (missing.size > 0) {
|
|
65
|
+
throw new Error(`platform function(s) no -p package provides: ${[...missing].sort().join(', ')} — ` +
|
|
66
|
+
'pass the implementing package with -p');
|
|
67
|
+
}
|
|
68
|
+
const name = options.name ?? basename(path, extname(path));
|
|
69
|
+
return East.exportFunctions(name, options.version ?? '0.0.0', functions, { providers });
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=export-functions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-functions.js","sourceRoot":"","sources":["../src/export-functions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,IAAI,EAAyB,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAc3C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,UAAkB,EAAE,UAAkC,EAAE;IACpG,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC;IACnC,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,qEAAqE,CAAC,CAAC;IACxG,CAAC;IACD,IAAI,SAAS,GAAG,QAAmC,CAAC;IACpD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC;QAClE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CACX,GAAG,UAAU,uBAAuB,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;gBAC1H,yBAAyB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACvC,KAAK,MAAM,EAAE,IAAI,MAAM,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,SAAS,CAAC;gBAAE,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QAC1D,CAAC;IACL,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,EAAE,CAAC;YAC9C,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,SAAS,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC;IACL,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACX,gDAAgD,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YACnF,uCAAuC,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO,EAAE,SAAgB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;AACnG,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-functions.spec.d.ts","sourceRoot":"","sources":["../src/export-functions.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
* Tests for `east-node export-functions` (#628): a module's `eastFunctions`
|
|
7
|
+
* export becomes a manifest that links and runs; unprovided platform
|
|
8
|
+
* dependencies and a missing export are named.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it } from 'node:test';
|
|
11
|
+
import assert from 'node:assert/strict';
|
|
12
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { tmpdir } from 'node:os';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { East, EastIR, FunctionType, IntegerType } from '@elaraai/east';
|
|
16
|
+
import { exportFunctionsFromModule } from './export-functions.js';
|
|
17
|
+
const EAST = import.meta.resolve('@elaraai/east');
|
|
18
|
+
const MODULE = `
|
|
19
|
+
import { East, IntegerType, NullType, StringType } from ${JSON.stringify(EAST)};
|
|
20
|
+
const log = East.platform("log", [StringType], NullType);
|
|
21
|
+
export const double = East.function([IntegerType], IntegerType, ($, x) => x.multiply(2n));
|
|
22
|
+
export const shout = East.function([StringType], NullType, ($, s) => { $(log(s.upperCase())); });
|
|
23
|
+
export const eastFunctions = { double, shout };
|
|
24
|
+
`;
|
|
25
|
+
/**
|
|
26
|
+
* Plants the module under a fake project that also provides the `log`
|
|
27
|
+
* platform as its own `./platform` package (`acme-platform`), the way the
|
|
28
|
+
* loader resolves a project's platform from the cwd.
|
|
29
|
+
*/
|
|
30
|
+
function plant(source) {
|
|
31
|
+
const dir = mkdtempSync(join(tmpdir(), 'enc-export-'));
|
|
32
|
+
const path = join(dir, 'pricing.mjs');
|
|
33
|
+
writeFileSync(path, source, 'utf-8');
|
|
34
|
+
const pkg = join(dir, 'node_modules', 'acme-platform');
|
|
35
|
+
mkdirSync(join(pkg, 'dist'), { recursive: true });
|
|
36
|
+
writeFileSync(join(pkg, 'package.json'), JSON.stringify({
|
|
37
|
+
name: 'acme-platform', version: '1.0.0', type: 'module',
|
|
38
|
+
exports: { './platform': './dist/platform.js', './package.json': './package.json' },
|
|
39
|
+
}));
|
|
40
|
+
writeFileSync(join(pkg, 'dist', 'platform.js'), 'export default [{ name: "log", inputs: [{ type: "String", value: null }], output: { type: "Null", value: null }, type: "sync", fn: () => null }];\n');
|
|
41
|
+
return { dir, path };
|
|
42
|
+
}
|
|
43
|
+
/** Runs `fn` with `process.cwd()` at `dir`, where the fake platform package resolves. */
|
|
44
|
+
async function withCwd(dir, fn) {
|
|
45
|
+
const prev = process.cwd();
|
|
46
|
+
process.chdir(dir);
|
|
47
|
+
try {
|
|
48
|
+
return await fn();
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
process.chdir(prev);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
describe('east-node export-functions', () => {
|
|
55
|
+
it('writes a manifest that links and runs, recording each dependency\'s provider', async () => {
|
|
56
|
+
const { dir, path } = plant(MODULE);
|
|
57
|
+
try {
|
|
58
|
+
const manifest = await withCwd(dir, () => exportFunctionsFromModule(path, { version: '2.0.0', packages: ['acme-platform'] }));
|
|
59
|
+
assert.equal(manifest.package, 'pricing');
|
|
60
|
+
assert.equal(manifest.version, '2.0.0');
|
|
61
|
+
assert.deepEqual(manifest.functions.map(f => f.name), ['double', 'shout']);
|
|
62
|
+
assert.equal(manifest.functions[1].platforms[0].provider.value, 'acme-platform');
|
|
63
|
+
const back = East.decodeFunctionManifest(East.encodeFunctionManifest(manifest));
|
|
64
|
+
const imported = East.importFunction('pricing', 'double', FunctionType([IntegerType], IntegerType));
|
|
65
|
+
const user = East.function([IntegerType], IntegerType, ($, x) => imported(x).add(1n));
|
|
66
|
+
const { ir } = East.linkImports(user, [back]);
|
|
67
|
+
assert.equal(new EastIR(ir).compile([])(4n), 9n);
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
rmSync(dir, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
it('names a platform dependency no package provides', async () => {
|
|
74
|
+
const { dir, path } = plant(MODULE);
|
|
75
|
+
try {
|
|
76
|
+
await assert.rejects(exportFunctionsFromModule(path, {}), /no -p package provides: log/);
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
rmSync(dir, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
it('exports only the named functions — a sibling\'s unprovided platform call no longer matters — and names an unknown one', async () => {
|
|
83
|
+
const { dir, path } = plant(MODULE);
|
|
84
|
+
try {
|
|
85
|
+
// `shout` calls `log`, which no -p package provides here; exporting `double` alone is fine
|
|
86
|
+
const manifest = await exportFunctionsFromModule(path, { only: ['double'] });
|
|
87
|
+
assert.deepEqual(manifest.functions.map(f => f.name), ['double']);
|
|
88
|
+
await assert.rejects(exportFunctionsFromModule(path, { only: ['double', 'nope'] }), /exports no function "nope" — its eastFunctions are double, shout/);
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
rmSync(dir, { recursive: true, force: true });
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
it('needs the eastFunctions export', async () => {
|
|
95
|
+
const { dir, path } = plant('export const x = 1;\n');
|
|
96
|
+
try {
|
|
97
|
+
await assert.rejects(exportFunctionsFromModule(path, {}), /exports no `eastFunctions` object/);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
rmSync(dir, { recursive: true, force: true });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=export-functions.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-functions.spec.js","sourceRoot":"","sources":["../src/export-functions.spec.ts"],"names":[],"mappings":"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"}
|
package/dist/loader.d.ts
CHANGED
|
@@ -79,6 +79,15 @@ export declare function loadEastIR(filePath: string): EastIR<any, any> | AsyncEa
|
|
|
79
79
|
* @returns Decoded value
|
|
80
80
|
*/
|
|
81
81
|
export declare function loadInput(filePath: string, type: EastTypeValue): unknown;
|
|
82
|
+
/**
|
|
83
|
+
* Bytes a value from {@link loadInputLazy} has read from its file so far:
|
|
84
|
+
* the geometry (tail and head), every fence probe, and each segment frame
|
|
85
|
+
* decoded. `undefined` for any other value.
|
|
86
|
+
*
|
|
87
|
+
* @param value - a task input value
|
|
88
|
+
* @returns the byte count, or `undefined` when the value was not opened lazily
|
|
89
|
+
*/
|
|
90
|
+
export declare function lazyInputBytesRead(value: unknown): number | undefined;
|
|
82
91
|
/**
|
|
83
92
|
* Opens an input file as a lazy pager-backed collection value, when it can
|
|
84
93
|
* be: a beast2 v5 collection blob carrying a segment index. Size, iteration
|
|
@@ -86,10 +95,17 @@ export declare function loadInput(filePath: string, type: EastTypeValue): unknow
|
|
|
86
95
|
* memory; any other operation hydrates transparently to the eager value's
|
|
87
96
|
* exact semantics.
|
|
88
97
|
*
|
|
98
|
+
* The file is never buffered whole: the value pages segment frames from an
|
|
99
|
+
* open descriptor through positioned reads (a Set or Dict input's first
|
|
100
|
+
* keyed read probes every segment's fence once), so its residency is the
|
|
101
|
+
* page cache and the process heap holds one decoded segment at a time — the
|
|
102
|
+
* difference between an out-of-memory kill and graceful eviction for an
|
|
103
|
+
* input near the runner's memory limit.
|
|
104
|
+
*
|
|
89
105
|
* Returns `undefined` when the file cannot be served lazily (a non-beast2
|
|
90
|
-
* format, a v4 or index-less blob, a non-collection root,
|
|
91
|
-
* shape carrying a `Ref` or function values) — the
|
|
92
|
-
* {@link loadInput}.
|
|
106
|
+
* format, a v4 or index-less blob, a non-collection root, cross-segment
|
|
107
|
+
* aliasing, or an element shape carrying a `Ref` or function values) — the
|
|
108
|
+
* caller falls back to {@link loadInput}.
|
|
93
109
|
*
|
|
94
110
|
* The value opens **frozen**, like every task input, which is what makes
|
|
95
111
|
* lazy service safe for any nested element shape: frozen values cannot be
|
package/dist/loader.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAWH,MAAM,EACN,WAAW,EACX,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAWH,MAAM,EACN,WAAW,EACX,KAAK,aAAa,EAErB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAWhF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,GAAG,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAsDD;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAyCnF;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsB7F;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CASvF;AAmDD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC,CAgCxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAuBrF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAoBxE;AAMD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAErE;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAiCnE"}
|
package/dist/loader.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
|
-
import { readFileSync } from 'fs';
|
|
5
|
+
import { closeSync, fstatSync, openSync, readFileSync, readSync } from 'fs';
|
|
6
6
|
import { createRequire } from 'module';
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import { extname } from 'path';
|
|
@@ -299,6 +299,31 @@ export function loadInput(filePath, type) {
|
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
|
+
/** Bytes each lazily opened input has read from its descriptor so far —
|
|
303
|
+
* what "paged from the file" came to, for the runner's verbose summary. */
|
|
304
|
+
const lazyInputReads = new WeakMap();
|
|
305
|
+
/**
|
|
306
|
+
* Bytes a value from {@link loadInputLazy} has read from its file so far:
|
|
307
|
+
* the geometry (tail and head), every fence probe, and each segment frame
|
|
308
|
+
* decoded. `undefined` for any other value.
|
|
309
|
+
*
|
|
310
|
+
* @param value - a task input value
|
|
311
|
+
* @returns the byte count, or `undefined` when the value was not opened lazily
|
|
312
|
+
*/
|
|
313
|
+
export function lazyInputBytesRead(value) {
|
|
314
|
+
return typeof value === 'object' && value !== null ? lazyInputReads.get(value)?.() : undefined;
|
|
315
|
+
}
|
|
316
|
+
/** The descriptors behind lazily opened inputs, closed when their value is
|
|
317
|
+
* collected: the value reads segment frames from the descriptor for its
|
|
318
|
+
* whole life. A runner holds one per lazy input. */
|
|
319
|
+
const lazyInputFiles = new FinalizationRegistry((fd) => {
|
|
320
|
+
try {
|
|
321
|
+
closeSync(fd);
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
// Already closed — nothing else to release.
|
|
325
|
+
}
|
|
326
|
+
});
|
|
302
327
|
/**
|
|
303
328
|
* Opens an input file as a lazy pager-backed collection value, when it can
|
|
304
329
|
* be: a beast2 v5 collection blob carrying a segment index. Size, iteration
|
|
@@ -306,10 +331,17 @@ export function loadInput(filePath, type) {
|
|
|
306
331
|
* memory; any other operation hydrates transparently to the eager value's
|
|
307
332
|
* exact semantics.
|
|
308
333
|
*
|
|
334
|
+
* The file is never buffered whole: the value pages segment frames from an
|
|
335
|
+
* open descriptor through positioned reads (a Set or Dict input's first
|
|
336
|
+
* keyed read probes every segment's fence once), so its residency is the
|
|
337
|
+
* page cache and the process heap holds one decoded segment at a time — the
|
|
338
|
+
* difference between an out-of-memory kill and graceful eviction for an
|
|
339
|
+
* input near the runner's memory limit.
|
|
340
|
+
*
|
|
309
341
|
* Returns `undefined` when the file cannot be served lazily (a non-beast2
|
|
310
|
-
* format, a v4 or index-less blob, a non-collection root,
|
|
311
|
-
* shape carrying a `Ref` or function values) — the
|
|
312
|
-
* {@link loadInput}.
|
|
342
|
+
* format, a v4 or index-less blob, a non-collection root, cross-segment
|
|
343
|
+
* aliasing, or an element shape carrying a `Ref` or function values) — the
|
|
344
|
+
* caller falls back to {@link loadInput}.
|
|
313
345
|
*
|
|
314
346
|
* The value opens **frozen**, like every task input, which is what makes
|
|
315
347
|
* lazy service safe for any nested element shape: frozen values cannot be
|
|
@@ -324,15 +356,41 @@ export function loadInput(filePath, type) {
|
|
|
324
356
|
export function loadInputLazy(filePath) {
|
|
325
357
|
if (getFileFormat(filePath) !== 'beast2')
|
|
326
358
|
return undefined;
|
|
327
|
-
|
|
359
|
+
let fd = -1;
|
|
328
360
|
try {
|
|
329
|
-
|
|
330
|
-
|
|
361
|
+
fd = openSync(filePath, 'r');
|
|
362
|
+
const handle = fd;
|
|
363
|
+
let bytesRead = 0;
|
|
364
|
+
const reader = {
|
|
365
|
+
size: fstatSync(handle).size,
|
|
366
|
+
read(offset, length) {
|
|
367
|
+
const out = new Uint8Array(length);
|
|
368
|
+
let done = 0;
|
|
369
|
+
while (done < length) {
|
|
370
|
+
const n = readSync(handle, out, done, length - done, offset + done);
|
|
371
|
+
if (n === 0)
|
|
372
|
+
throw new Error(`beast2: short read at offset ${offset + done}`);
|
|
373
|
+
done += n;
|
|
374
|
+
}
|
|
375
|
+
bytesRead += length;
|
|
376
|
+
return out;
|
|
377
|
+
},
|
|
378
|
+
};
|
|
379
|
+
const extents = readBeast2Extents(reader);
|
|
380
|
+
if (!extents.selfContained || !isBeast2LazySafe(extents.typeValue, { frozen: true }))
|
|
331
381
|
return undefined;
|
|
332
|
-
|
|
382
|
+
const value = openBeast2LazyFor(extents.typeValue, { frozen: true })(reader);
|
|
383
|
+
lazyInputFiles.register(value, handle);
|
|
384
|
+
lazyInputReads.set(value, () => bytesRead);
|
|
385
|
+
fd = -1; // the value owns the descriptor from here
|
|
386
|
+
return value;
|
|
333
387
|
}
|
|
334
388
|
catch {
|
|
335
389
|
return undefined;
|
|
336
390
|
}
|
|
391
|
+
finally {
|
|
392
|
+
if (fd >= 0)
|
|
393
|
+
closeSync(fd);
|
|
394
|
+
}
|
|
337
395
|
}
|
|
338
396
|
//# sourceMappingURL=loader.js.map
|