@elaraai/create-e3 1.0.68 → 1.0.69
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/dist/index.js +17 -11
- package/package.json +1 -1
- package/templates/e3/README.md +7 -0
- package/templates/e3/_packages/c/_app.ts +5 -0
- package/templates/e3/_packages/node/_app.ts +36 -4
- package/templates/e3/_packages/node/package.json +1 -0
- package/templates/e3/_packages/node/src/functions.ts +29 -0
- package/templates/e3/_packages/python/_app.ts +34 -4
- package/templates/e3/_packages/python/src/__PACKAGE_NAME__/__init__.py +20 -9
- package/templates/e3/_packages/python/src/__PACKAGE_NAME__/functions.py +29 -0
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ var RUNTIMES = {
|
|
|
28
28
|
destParent: "packages/python",
|
|
29
29
|
templateName: "python",
|
|
30
30
|
label: "Python",
|
|
31
|
+
tasks: 2,
|
|
31
32
|
valid: /^[a-z][a-z0-9_]*$/,
|
|
32
33
|
rule: "lowercase letters, digits and underscores, starting with a letter"
|
|
33
34
|
},
|
|
@@ -37,6 +38,7 @@ var RUNTIMES = {
|
|
|
37
38
|
destParent: "packages/node",
|
|
38
39
|
templateName: "node",
|
|
39
40
|
label: "Node",
|
|
41
|
+
tasks: 2,
|
|
40
42
|
valid: /^[a-z][a-z0-9-]*$/,
|
|
41
43
|
rule: "lowercase letters, digits and hyphens, starting with a letter"
|
|
42
44
|
},
|
|
@@ -46,6 +48,7 @@ var RUNTIMES = {
|
|
|
46
48
|
destParent: "packages/native",
|
|
47
49
|
templateName: "c",
|
|
48
50
|
label: "C",
|
|
51
|
+
tasks: 1,
|
|
49
52
|
valid: /^[a-z][a-z0-9_-]*$/,
|
|
50
53
|
rule: "lowercase letters, digits, underscores and hyphens, starting with a letter"
|
|
51
54
|
}
|
|
@@ -146,11 +149,13 @@ function excludePackagesFromRootTsconfig(projectDir) {
|
|
|
146
149
|
`);
|
|
147
150
|
}
|
|
148
151
|
function writeAppWiring(projectDir, names, members) {
|
|
149
|
-
const imports = members.map((m) => `import { ${m.ident}
|
|
150
|
-
const list = members.map((m) => `
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
//
|
|
152
|
+
const imports = members.map((m) => `import { ${m.ident}_tasks } from "./${m.name}.js";`).join("\n");
|
|
153
|
+
const list = members.map((m) => ` ...${m.ident}_tasks,`).join("\n");
|
|
154
|
+
const taskCount = members.reduce((n, m) => n + RUNTIMES[m.runtime].tasks, 0);
|
|
155
|
+
const barrel = `// Generated by create-e3 \u2014 collects the example tasks of every workspace package:
|
|
156
|
+
// a call of the package's platform function (its environment derived from the
|
|
157
|
+
// package) and, for python and node, a call of an East function the package
|
|
158
|
+
// exports (embedded at export). Add packages with \`create-e3 --python-packages=\u2026\`.
|
|
154
159
|
${imports}
|
|
155
160
|
|
|
156
161
|
export const packageTasks = [
|
|
@@ -163,10 +168,11 @@ ${list}
|
|
|
163
168
|
|
|
164
169
|
import { packageTasks } from "./packages/index.js";
|
|
165
170
|
|
|
166
|
-
// This app wires
|
|
167
|
-
// task's \`environment\` is captured
|
|
168
|
-
// re-runs only its
|
|
169
|
-
//
|
|
171
|
+
// This app wires the example tasks of each generated workspace package. A
|
|
172
|
+
// platform-function task's \`environment\` is captured per package, so editing
|
|
173
|
+
// one package re-runs only its tasks \u2014 the other packages stay cached; an
|
|
174
|
+
// imported East function is embedded at export and runs anywhere. Add your
|
|
175
|
+
// own inputs, tasks and dataflows here.
|
|
170
176
|
export default e3.package("${names.projectName}", "1.0.0", ...packageTasks);
|
|
171
177
|
`;
|
|
172
178
|
writeFileSync(join(projectDir, "src", "index.ts"), index);
|
|
@@ -180,9 +186,9 @@ import { packageTasks } from "./packages/index.js";
|
|
|
180
186
|
// Generated by create-e3 \u2014 smoke tests for the generated multi-package
|
|
181
187
|
// app. Replace with real tests as you add inputs, tasks and dataflows.
|
|
182
188
|
describeEast("${names.displayName}", (test) => {
|
|
183
|
-
test("wires
|
|
189
|
+
test("wires every example task of every workspace package", ($) => {
|
|
184
190
|
const count = $.const(BigInt(packageTasks.length), IntegerType);
|
|
185
|
-
$(Assert.equal(count, East.value(${
|
|
191
|
+
$(Assert.equal(count, East.value(${taskCount}n)));
|
|
186
192
|
});
|
|
187
193
|
|
|
188
194
|
test("exports the deployable package", ($) => {
|
package/package.json
CHANGED
package/templates/e3/README.md
CHANGED
|
@@ -51,3 +51,10 @@ anything was skipped; `npm run shots:html` adds a standalone HTML beside each PN
|
|
|
51
51
|
If you scaffolded with `--platform`, `src/platform/` holds project-owned TS-East platform functions
|
|
52
52
|
(exported via `./platform`) and `platform_module/` holds the Python ones — replace the generated
|
|
53
53
|
`example` functions with your own native code, called from tasks like any East function.
|
|
54
|
+
|
|
55
|
+
If you scaffolded with `--python-packages` / `--node-packages` / `--c-packages`, each package under
|
|
56
|
+
`packages/` is its own execution environment, and every python and node package crosses the language
|
|
57
|
+
boundary both ways: a platform function (`example.py` / `src/platform.ts` — native code the task's
|
|
58
|
+
runner needs installed) and an East function (`functions.py` / `src/functions.ts` — East IR the app
|
|
59
|
+
imports with `East.importFunction`; e3 embeds it at export, so it runs anywhere). The app-side wiring
|
|
60
|
+
of each package is `src/packages/<name>.ts`.
|
|
@@ -20,3 +20,8 @@ export const __PACKAGE_IDENT___task = e3.customTask(
|
|
|
20
20
|
environment: { tools: { files: ["packages/native/__PACKAGE_NAME__/build/__PACKAGE_NAME__"] } },
|
|
21
21
|
},
|
|
22
22
|
);
|
|
23
|
+
|
|
24
|
+
// Every task this package contributes to the app's dataflow (collected by
|
|
25
|
+
// src/packages/index.ts). A C package crosses the boundary one way — the built
|
|
26
|
+
// tool; C has no East authoring surface to export a function from.
|
|
27
|
+
export const __PACKAGE_IDENT___tasks = [__PACKAGE_IDENT___task];
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import e3 from "@elaraai/e3";
|
|
2
|
-
import { East, IntegerType, FloatType } from "@elaraai/east";
|
|
2
|
+
import { East, ArrayType, IntegerType, FloatType, FunctionType } from "@elaraai/east";
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Two ways of crossing the package boundary into packages/node/__PACKAGE_NAME__
|
|
5
|
+
// (@__PROJECT_NAME__/__PACKAGE_NAME__):
|
|
6
|
+
//
|
|
7
|
+
// 1. A PLATFORM function — native Node code East cannot express. This TS-East
|
|
8
|
+
// declaration mirrors packages/node/__PACKAGE_NAME__/src/platform.ts (same
|
|
9
|
+
// dotted "__PACKAGE_NAME__.example" name + signature — keep the two in lockstep),
|
|
10
|
+
// and the task calling it runs on east-node with the package installed.
|
|
7
11
|
const example = East.platform("__PACKAGE_NAME__.example", [IntegerType, FloatType], IntegerType);
|
|
8
12
|
|
|
13
|
+
// 2. An EAST function — East IR authored in the package (…/src/functions.ts,
|
|
14
|
+
// listed in its `eastFunctions`), referred to by package, name and type. At
|
|
15
|
+
// export e3 finds the package in the npm workspace, exports its functions from
|
|
16
|
+
// the built ./functions entry (east-node export-functions) and embeds the IR in
|
|
17
|
+
// the task: the deployed program is pure IR, so the task needs no platform and
|
|
18
|
+
// no environment. The type must equal the exported one exactly — e3 checks it
|
|
19
|
+
// at export.
|
|
20
|
+
const scale = East.importFunction(
|
|
21
|
+
"@__PROJECT_NAME__/__PACKAGE_NAME__",
|
|
22
|
+
"scale",
|
|
23
|
+
FunctionType([ArrayType(FloatType), FloatType], ArrayType(FloatType)),
|
|
24
|
+
);
|
|
25
|
+
|
|
9
26
|
const value = e3.input("__PACKAGE_IDENT___value", IntegerType, 21n);
|
|
10
27
|
const factor = e3.input("__PACKAGE_IDENT___factor", FloatType, 2.0);
|
|
28
|
+
const series = e3.input("__PACKAGE_IDENT___series", ArrayType(FloatType), [1.0, 2.0, 3.0]);
|
|
11
29
|
|
|
12
30
|
// No `environment` — e3 derives it from the `{ custom: "@__PROJECT_NAME__/__PACKAGE_NAME__" }`
|
|
13
31
|
// platform reference below, capturing packages/node/__PACKAGE_NAME__'s npm
|
|
@@ -23,3 +41,17 @@ export const __PACKAGE_IDENT___task = e3.task(
|
|
|
23
41
|
runner: { runtime: "east-node", platforms: [{ custom: "@__PROJECT_NAME__/__PACKAGE_NAME__" }] },
|
|
24
42
|
},
|
|
25
43
|
);
|
|
44
|
+
|
|
45
|
+
// The imported East function needs no runner, platform or environment: its IR is
|
|
46
|
+
// embedded here at export, and the default runner executes it.
|
|
47
|
+
export const __PACKAGE_IDENT___scaled_task = e3.task(
|
|
48
|
+
"__PACKAGE_IDENT___scaled",
|
|
49
|
+
[series, factor],
|
|
50
|
+
East.function([ArrayType(FloatType), FloatType], ArrayType(FloatType), ($, s, f) => {
|
|
51
|
+
$.return(scale(s, f));
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// Every task this package contributes to the app's dataflow (collected by
|
|
56
|
+
// src/packages/index.ts).
|
|
57
|
+
export const __PACKAGE_IDENT___tasks = [__PACKAGE_IDENT___task, __PACKAGE_IDENT___scaled_task];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { East, ArrayType, FloatType } from "@elaraai/east";
|
|
2
|
+
|
|
3
|
+
// An East function owned by @__PROJECT_NAME__/__PACKAGE_NAME__ — East all the way down.
|
|
4
|
+
//
|
|
5
|
+
// platform.ts is the other way across the package boundary: a platform function
|
|
6
|
+
// wraps NATIVE Node code East cannot express, and the task calling it runs on
|
|
7
|
+
// east-node with this package installed. An East function is built here with
|
|
8
|
+
// `East.function`, so it IS East IR: the app refers to it by package, name and
|
|
9
|
+
// type (East.importFunction("@__PROJECT_NAME__/__PACKAGE_NAME__", "scale", …) in
|
|
10
|
+
// src/packages/__PACKAGE_NAME__.ts), and at export e3 finds this package in the
|
|
11
|
+
// npm workspace, exports every function in `eastFunctions` from the BUILT
|
|
12
|
+
// `./functions` entry (east-node export-functions on dist/functions.js — build
|
|
13
|
+
// first) and embeds the IR in the task. The deployed program is pure IR and runs
|
|
14
|
+
// on any runner, with nothing installed where it runs.
|
|
15
|
+
//
|
|
16
|
+
// To add a function: build it here and add it to `eastFunctions` under the name
|
|
17
|
+
// the app imports. The app declares the same FunctionType — the two must be
|
|
18
|
+
// equal exactly, and e3 checks that at export.
|
|
19
|
+
|
|
20
|
+
// Scale every value by a factor. The parameters are East expressions and `.map`
|
|
21
|
+
// builds East IR — nothing here runs in Node.
|
|
22
|
+
export const scale = East.function(
|
|
23
|
+
[ArrayType(FloatType), FloatType],
|
|
24
|
+
ArrayType(FloatType),
|
|
25
|
+
($, values, factor) => values.map(($, v) => v.multiply(factor)),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// The East functions this package exports, by the name the app imports them under.
|
|
29
|
+
export const eastFunctions = { scale };
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import e3 from "@elaraai/e3";
|
|
2
|
-
import { East, ArrayType, FloatType } from "@elaraai/east";
|
|
2
|
+
import { East, ArrayType, FloatType, FunctionType } from "@elaraai/east";
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Two ways of crossing the language boundary into packages/python/__PACKAGE_NAME__:
|
|
5
|
+
//
|
|
6
|
+
// 1. A PLATFORM function — native python East cannot express. This TS-East
|
|
7
|
+
// declaration mirrors packages/python/__PACKAGE_NAME__/src/__PACKAGE_NAME__/example.py
|
|
8
|
+
// (same dotted "__PACKAGE_NAME__.example" name, same signature — keep the two in
|
|
9
|
+
// lockstep), and the task calling it runs on east-py with the package installed.
|
|
7
10
|
const example = East.platform("__PACKAGE_NAME__.example", [ArrayType(FloatType)], FloatType);
|
|
8
11
|
|
|
12
|
+
// 2. An EAST function — East IR authored in python (…/functions.py, listed in the
|
|
13
|
+
// package's `east_functions`), referred to by package, name and type. At export
|
|
14
|
+
// e3 finds the package in the uv workspace, exports its functions (east-py
|
|
15
|
+
// export-functions) and embeds the IR in the task: the deployed program is pure
|
|
16
|
+
// IR, so the task runs on the DEFAULT runner (east-node) with no python at run
|
|
17
|
+
// time. The type must equal the exported one exactly — e3 checks it at export.
|
|
18
|
+
const scale = East.importFunction(
|
|
19
|
+
"__PACKAGE_NAME__",
|
|
20
|
+
"scale",
|
|
21
|
+
FunctionType([ArrayType(FloatType), FloatType], ArrayType(FloatType)),
|
|
22
|
+
);
|
|
23
|
+
|
|
9
24
|
const values = e3.input("__PACKAGE_IDENT___values", ArrayType(FloatType), [1.0, 2.0, 3.0]);
|
|
25
|
+
const factor = e3.input("__PACKAGE_IDENT___factor", FloatType, 2.0);
|
|
10
26
|
|
|
11
27
|
// No `environment` needed: e3 derives it from the `{ custom: "__PACKAGE_NAME__" }`
|
|
12
28
|
// platform reference below — at export it captures packages/python/__PACKAGE_NAME__'s
|
|
@@ -24,3 +40,17 @@ export const __PACKAGE_IDENT___task = e3.task(
|
|
|
24
40
|
runner: { runtime: "east-py", platforms: [{ custom: "__PACKAGE_NAME__" }, "east-py-std"] },
|
|
25
41
|
},
|
|
26
42
|
);
|
|
43
|
+
|
|
44
|
+
// The imported East function needs no runner, platform or environment: its IR is
|
|
45
|
+
// embedded here at export, and the default runner executes it.
|
|
46
|
+
export const __PACKAGE_IDENT___scaled_task = e3.task(
|
|
47
|
+
"__PACKAGE_IDENT___scaled",
|
|
48
|
+
[values, factor],
|
|
49
|
+
East.function([ArrayType(FloatType), FloatType], ArrayType(FloatType), ($, v, f) => {
|
|
50
|
+
$.return(scale(v, f));
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// Every task this package contributes to the app's dataflow (collected by
|
|
55
|
+
// src/packages/index.ts).
|
|
56
|
+
export const __PACKAGE_IDENT___tasks = [__PACKAGE_IDENT___task, __PACKAGE_IDENT___scaled_task];
|
|
@@ -1,18 +1,29 @@
|
|
|
1
|
-
"""The ``__PACKAGE_NAME__``
|
|
1
|
+
"""The ``__PACKAGE_NAME__`` package — its own execution environment, and both ways
|
|
2
|
+
of crossing the language boundary.
|
|
2
3
|
|
|
3
4
|
Everything under ``packages/python/__PACKAGE_NAME__`` is captured as ONE
|
|
4
|
-
environment when a task wired to it is exported
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
environment when a task wired to it is exported: e3 derives it from the task's
|
|
6
|
+
``{ custom: "__PACKAGE_NAME__" }`` platform reference. Editing this package
|
|
7
|
+
changes only its environment hash, so only the tasks wired to it re-run —
|
|
8
|
+
sibling packages are left untouched. That package boundary IS the
|
|
8
9
|
change-detection granularity.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
Two things cross from here into the app's TypeScript tasks:
|
|
12
|
+
|
|
13
|
+
- ``platform`` — the platform functions (``example.py``): NATIVE python that
|
|
14
|
+
East cannot express. ``east-py run -p __PACKAGE_NAME__`` imports this package
|
|
15
|
+
and reads the list. To add one: create a module beside this file (e.g.
|
|
16
|
+
``pricing.py``) ending with ``pricing_impl = platform_functions(__name__)``,
|
|
17
|
+
then import and spread it into ``platform``.
|
|
18
|
+
- ``east_functions`` — the East functions (``functions.py``): East IR authored
|
|
19
|
+
in python, imported by the app with ``East.importFunction`` and embedded at
|
|
20
|
+
export, so they run on any runner with no python at run time. To add one:
|
|
21
|
+
build it and add it here under the name the app imports.
|
|
14
22
|
"""
|
|
15
23
|
|
|
16
24
|
from .example import example_impl
|
|
25
|
+
from .functions import scale
|
|
17
26
|
|
|
18
27
|
platform = [*example_impl]
|
|
28
|
+
|
|
29
|
+
east_functions = {"scale": scale}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""An East function owned by the ``__PACKAGE_NAME__`` package — East all the way down.
|
|
2
|
+
|
|
3
|
+
``example.py`` is the other way across the language boundary: a platform
|
|
4
|
+
function wraps NATIVE python that East cannot express, and the task calling it
|
|
5
|
+
runs on east-py with this package installed. An East function is authored in
|
|
6
|
+
python but built with east-py's ``East.function``, so it IS East IR: the app's
|
|
7
|
+
TypeScript task refers to it by package, name and type
|
|
8
|
+
(``East.importFunction("__PACKAGE_NAME__", "scale", …)`` in
|
|
9
|
+
``src/packages/__PACKAGE_NAME__.ts``), and at export e3 finds this package in
|
|
10
|
+
the uv workspace, exports every function in ``east_functions`` (``east-py
|
|
11
|
+
export-functions``) and embeds the IR in the task. The deployed program is pure
|
|
12
|
+
IR — it runs on ANY runner, the default east-node one included, with no python
|
|
13
|
+
at run time and nothing installed where it runs.
|
|
14
|
+
|
|
15
|
+
To add a function: build it here (or in a module beside this one) and add it to
|
|
16
|
+
``east_functions`` in ``__init__.py`` under the name the app imports. The app
|
|
17
|
+
declares the same type with ``FunctionType([...], Out)`` — the two must be equal
|
|
18
|
+
exactly, and e3 checks that at export.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from east import ArrayType, East, FloatType
|
|
22
|
+
|
|
23
|
+
# Scale every value by a factor. The parameters are East expressions and `.map`
|
|
24
|
+
# builds East IR — nothing here runs in python.
|
|
25
|
+
scale = East.function(
|
|
26
|
+
[ArrayType(FloatType), FloatType],
|
|
27
|
+
ArrayType(FloatType),
|
|
28
|
+
lambda b, values, factor: values.map(lambda b, v: v * factor),
|
|
29
|
+
)
|