@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 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}_task } from "./${m.name}.js";`).join("\n");
150
- const list = members.map((m) => ` ${m.ident}_task,`).join("\n");
151
- const barrel = `// Generated by create-e3 \u2014 collects one example task per workspace package.
152
- // Each task's \`environment\` points at its package, so editing one package
153
- // re-runs only its task. Add packages with \`create-e3 --python-packages=\u2026\`.
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 one example task per generated workspace package. Every
167
- // task's \`environment\` is captured independently, so editing one package
168
- // re-runs only its task \u2014 the other packages stay cached. Add your own
169
- // inputs, tasks and dataflows here.
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 one task per workspace package", ($) => {
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(${members.length}n)));
191
+ $(Assert.equal(count, East.value(${taskCount}n)));
186
192
  });
187
193
 
188
194
  test("exports the deployable package", ($) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elaraai/create-e3",
3
- "version": "1.0.68",
3
+ "version": "1.0.69",
4
4
  "description": "Scaffold a new e3 project (BSL-1.1, Node + Python, durable execution): npm create @elaraai/e3",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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
- // TS-East mirror of @__PROJECT_NAME__/__PACKAGE_NAME__'s platform function —
5
- // same dotted "__PACKAGE_NAME__.example" name + signature. Keep this in lockstep
6
- // with packages/node/__PACKAGE_NAME__/src/platform.ts.
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];
@@ -6,6 +6,7 @@
6
6
  "private": true,
7
7
  "exports": {
8
8
  "./platform": "./dist/platform.js",
9
+ "./functions": "./dist/functions.js",
9
10
  "./package.json": "./package.json"
10
11
  },
11
12
  "files": [
@@ -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
- // TS-East mirror of `packages/python/__PACKAGE_NAME__`'s @platform_function —
5
- // same dotted "__PACKAGE_NAME__.example" name, same signature. Keep this in
6
- // lockstep with packages/python/__PACKAGE_NAME__/src/__PACKAGE_NAME__/example.py.
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__`` platform package — its own execution environment.
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. Editing this package changes
5
- only its environment hash, so only the tasks that declare
6
- ``environment: { python: { project: "packages/python/__PACKAGE_NAME__" } }``
7
- re-run — sibling packages are left untouched. That package boundary IS the
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
- ``east-py run -p __PACKAGE_NAME__`` imports this package and reads the top-level
11
- ``platform`` list below. To add a function: create a module beside this file
12
- (e.g. ``pricing.py``) ending with ``pricing_impl = platform_functions(__name__)``,
13
- then import and spread it into ``platform``.
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
+ )