@elaraai/e3-cloud-codex-plugin 0.0.0-stage → 1.0.90-alpha.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/.build/hooks/codex-tools.js +306 -0
- package/.build/mcp/server.js +23610 -0
- package/.codex-plugin/plugin.json +34 -0
- package/.mcp.json +11 -0
- package/LICENSE.md +682 -0
- package/README.md +65 -2
- package/hooks/hooks.json +29 -0
- package/index.json +749 -0
- package/package.json +30 -4
- package/skills/e3-cloud-cli/SKILL.md +129 -0
- package/skills/e3-cloud-client/SKILL.md +76 -0
- package/skills/e3-cloud-ui/SKILL.md +108 -0
package/package.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elaraai/e3-cloud-codex-plugin",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.90-alpha.0",
|
|
4
|
+
"description": "e3 cloud - apps for hosted e3 workspaces with @elaraai/e3-cloud-ui, the e3-cloud CLI and @elaraai/e3-cloud-client: skills, example search and the search-first hooks",
|
|
5
|
+
"license": "AGPL-3.0-or-later",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Elara AI",
|
|
9
|
+
"email": "support@elara.ai",
|
|
10
|
+
"url": "https://elaraai.com"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/elaraai/plugins",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"e3",
|
|
15
|
+
"e3-cloud",
|
|
16
|
+
"east",
|
|
17
|
+
"elara",
|
|
18
|
+
"apps",
|
|
19
|
+
"typescript"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=22.0.0"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
".codex-plugin",
|
|
26
|
+
".build",
|
|
27
|
+
"hooks",
|
|
28
|
+
"skills",
|
|
29
|
+
".mcp.json",
|
|
30
|
+
"index.json"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: e3-cloud-cli
|
|
3
|
+
description: "The e3-cloud CLI — run an e3 cloud deployment from the shell. Use when: (1) Signing in (`e3 auth login` to a server, whose credentials e3-cloud shares) and checking who you are (`e3-cloud whoami`), (2) Building and deploying apps — `e3-cloud app build`, `app deploy` (UI-only, or with its package, `--dry-run`, several together, `--from-source`), `app list`, `app versions`, `app remove` (an app is developed in the cloud: deployed to a workspace of one's own and opened there), (3) Staging an app for the platform's next e3 (`app deploy --for-platform VERSION`, `app list-all`), (4) Staging and releases — `e3-cloud staging add|stop|list` (a staging protects the workspace it releases to: it then changes only by a release from it, or a rollback; `--force` on `app deploy` and `app remove` is an admin's override), `e3 workspace copy` for the rehearsal, `e3-cloud release URL FROM TO` with `--plan`, `--carry` and `--remove-apps`,… See the detailed scope below."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Detailed skill scope
|
|
7
|
+
|
|
8
|
+
The e3-cloud CLI — run an e3 cloud deployment from the shell. Use when: (1) Signing in (`e3 auth login` to a server, whose credentials e3-cloud shares) and checking who you are (`e3-cloud whoami`), (2) Building and deploying apps — `e3-cloud app build`, `app deploy` (UI-only, or with its package, `--dry-run`, several together, `--from-source`), `app list`, `app versions`, `app remove` (an app is developed in the cloud: deployed to a workspace of one's own and opened there), (3) Staging an app for the platform's next e3 (`app deploy --for-platform VERSION`, `app list-all`), (4) Staging and releases — `e3-cloud staging add|stop|list` (a staging protects the workspace it releases to: it then changes only by a release from it, or a rollback; `--force` on `app deploy` and `app remove` is an admin's override), `e3 workspace copy` for the rehearsal, `e3-cloud release URL FROM TO` with `--plan`, `--carry` and `--remove-apps`, `e3-cloud history`, `e3-cloud rollback`, (5) A repository's people and business roles — `e3-cloud user list|add|remove` (`--role owner`, or a user with `--roles 'Rostering,Finance'`), `e3-cloud role list|show|set|rm` (`--grant WORKSPACE/APP[:page,page]`), and for admins `user list-all|disable|enable|invitations|uninvite`, (6) Secrets (`e3-cloud secrets set|list|rm`), schedules (`schedule set|get|list|remove`), each task's compute size and timeout (`compute`, `timeout`), people's workspace settings (`settings`), (7) Records' history, rollback and backups (`e3-cloud records …`) and feedback (`e3-cloud feedback …`).
|
|
9
|
+
|
|
10
|
+
# e3-cloud — the e3 cloud CLI (@elaraai/e3-cloud-cli)
|
|
11
|
+
|
|
12
|
+
`e3-cloud` runs the parts of an e3 cloud deployment that e3's own CLI does not:
|
|
13
|
+
apps, releases, users and roles, secrets, schedules, task configs, records'
|
|
14
|
+
history and backups, and feedback. e3's CLI (`e3`, `@elaraai/e3-cli`) still
|
|
15
|
+
does what it does against any server: repositories, packages, workspaces,
|
|
16
|
+
datasets, dataflow runs and copies. Both sign in with `e3 auth login` and share its
|
|
17
|
+
credentials (`~/.e3/credentials.json`).
|
|
18
|
+
|
|
19
|
+
A command names what it acts on by URL: a server (`https://e3.example.com`),
|
|
20
|
+
a repository (`…/repos/acme`), or a workspace (`…/repos/acme/workspaces/production`),
|
|
21
|
+
as its help says.
|
|
22
|
+
|
|
23
|
+
## Before writing code — search the example index
|
|
24
|
+
|
|
25
|
+
Every command has an entry in the plugin's index, with the client calls and
|
|
26
|
+
the app library's. Before scripting a deployment or answering how a command
|
|
27
|
+
works:
|
|
28
|
+
|
|
29
|
+
1. Call `search_e3_cloud_examples` with what
|
|
30
|
+
you are about to do (`release staging to production`, `give a user a role`).
|
|
31
|
+
Summaries come back first.
|
|
32
|
+
2. Fetch the one or two that match with
|
|
33
|
+
`get_e3_cloud_example`.
|
|
34
|
+
3. Do not read `node_modules/@elaraai/**` instead: the index holds the same
|
|
35
|
+
commands, exact and far cheaper, and `e3-cloud <command> --help` the rest.
|
|
36
|
+
|
|
37
|
+
Nothing is injected for you; the search is the step.
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install -g @elaraai/e3-cloud-cli @elaraai/e3-cli
|
|
43
|
+
e3 auth login https://e3.example.com
|
|
44
|
+
e3-cloud whoami https://e3.example.com
|
|
45
|
+
|
|
46
|
+
# An app: build its bundle, check it, deploy it
|
|
47
|
+
e3-cloud app build src/apps/ops.tsx
|
|
48
|
+
e3-cloud app deploy https://e3.example.com/repos/acme staging dist/ops.app --dry-run
|
|
49
|
+
e3-cloud app deploy https://e3.example.com/repos/acme staging dist/ops.app
|
|
50
|
+
|
|
51
|
+
# Staging: a copy of production where changes are tried; production is protected from then on
|
|
52
|
+
e3-cloud staging add https://e3.example.com/repos/acme production staging
|
|
53
|
+
|
|
54
|
+
# A release: the plan first, then exactly what staging runs, production's data kept
|
|
55
|
+
e3-cloud release https://e3.example.com/repos/acme staging production --plan
|
|
56
|
+
e3-cloud release https://e3.example.com/repos/acme staging production
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Apps
|
|
60
|
+
|
|
61
|
+
- `app build <source>` writes the bundle (`dist/<app>.app`): the app and the
|
|
62
|
+
package it was built against. A refusal names each problem.
|
|
63
|
+
- `app deploy <repo-url> <workspace> [bundles…]` imports the bundle's package
|
|
64
|
+
when the repository lacks it, checks every app against it, and deploys: at
|
|
65
|
+
once when the workspace runs that package (UI only); else the package deploys
|
|
66
|
+
first, keeping the inputs people set, and the apps go live as it completes
|
|
67
|
+
(the CLI waits). `--dry-run` checks and changes nothing; `--from-source`
|
|
68
|
+
builds sources instead of bundles; several apps deploy together or not at all.
|
|
69
|
+
- An app is developed in the cloud, not locally: deploy it to a workspace
|
|
70
|
+
of your own (`--from-source` after each change, `--dry-run` to check
|
|
71
|
+
only) and open it in the console. Develop against a staging, never the
|
|
72
|
+
protected workspace it releases to.
|
|
73
|
+
- `app deploy` and `app remove` to a protected workspace are refused, naming
|
|
74
|
+
its staging; an admin alone forces one with `--force`, which warns first and
|
|
75
|
+
which the workspace's history records as forced.
|
|
76
|
+
- `app deploy … --for-platform <version>` stages a bundle built with the
|
|
77
|
+
platform's next e3; `app list-all` (admins) lists every app and which needs
|
|
78
|
+
one.
|
|
79
|
+
|
|
80
|
+
## Staging
|
|
81
|
+
|
|
82
|
+
A workspace's staging is where changes are tried before they reach the
|
|
83
|
+
workspace people use, which it then **protects**, as a protected branch is
|
|
84
|
+
protected: its package and apps change only by a release from its staging, or
|
|
85
|
+
a rollback. One staging to a workspace; no staging has one of its own.
|
|
86
|
+
|
|
87
|
+
- `staging add <repo-url> <live> <name>` prints what it would do, then adds it:
|
|
88
|
+
a copy of the live workspace as it is now, data included. `--plan` stops at
|
|
89
|
+
the plan; a workspace of the name is used `--as-is`, or replaced whole only
|
|
90
|
+
with `--replace`.
|
|
91
|
+
- `staging list <repo-url>` names each staging and what it protects;
|
|
92
|
+
`staging stop <repo-url> <live>` (admins alone) unprotects it, deleting
|
|
93
|
+
nothing.
|
|
94
|
+
- A protected workspace refuses e3's `workspace deploy`, an app deploy or
|
|
95
|
+
removal, a copy onto it, and its removal or its staging's. Its data goes on:
|
|
96
|
+
inputs, records, runs and schedules.
|
|
97
|
+
|
|
98
|
+
## Releases
|
|
99
|
+
|
|
100
|
+
A release gives the target exactly the package and app versions the source
|
|
101
|
+
runs, by hash, with the bundles it has staged for the next e3. Only the
|
|
102
|
+
target's staging releases to it. The target keeps the inputs people set in it,
|
|
103
|
+
migrates its records, and runs next by hand or on its schedule. Owners and
|
|
104
|
+
admins release.
|
|
105
|
+
|
|
106
|
+
- `e3 workspace copy <repo-url> production staging` makes staging production
|
|
107
|
+
as it is now, apps included: the rehearsal's first step before each change.
|
|
108
|
+
- `release <repo-url> <from> <to>` prints the plan first, then releases;
|
|
109
|
+
`--plan` stops at the plan. A refused plan prints why and exits 1, changing
|
|
110
|
+
nothing; one that would change nothing is refused. The plan names any change
|
|
111
|
+
an admin forced onto the target since its last release, which it undoes. `--carry <path…>` copies inputs, and records new in the release,
|
|
112
|
+
from the source by reference; `--remove-apps` removes the target's apps the
|
|
113
|
+
source lacks.
|
|
114
|
+
- `history <repo-url> <workspace>` lists each release, deploy, app deploy,
|
|
115
|
+
copy and rollback, with its id; `rollback <repo-url> <workspace> [<id>]`
|
|
116
|
+
releases an entry again, its package and apps exactly.
|
|
117
|
+
|
|
118
|
+
## Traps
|
|
119
|
+
|
|
120
|
+
- A release deploys the source's package by its version: re-importing a
|
|
121
|
+
package under the same version since the source deployed it refuses the
|
|
122
|
+
release (deploy the source again).
|
|
123
|
+
- A rollback past a record migration is refused: e3's deploy never migrates a
|
|
124
|
+
record back. A rollback stays open on a protected workspace.
|
|
125
|
+
- Sign in with `e3 auth login <server>`: there is no `e3 login`.
|
|
126
|
+
- `secrets set` reads the value from stdin unless `--value` is given; the
|
|
127
|
+
next run reads the new value.
|
|
128
|
+
- The version is the @elaraai lockstep: use the CLI of the release your
|
|
129
|
+
deployment runs.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: e3-cloud-client
|
|
3
|
+
description: "@elaraai/e3-cloud-client — drive an e3 cloud deployment from TypeScript. Use when: (1) Calling a deployment from code with a token (`whoami`, `RequestOptions`, `ApiError`), (2) Managing a repository's people and business roles (`repoUsers`, `addUser`, `removeUser`, `repoInvitations`, `listRoles`, `putRole`, `myAccess`), (3) Deploying apps from code — `appUpload`, `appDeploy` / `appsDeploy` and `appDeployWait`, `appList`, `appGet`, `appVersions`, `appRemove` — and reading a refusal (`appProblemsText`), (4) Staging, releasing and rolling back — `addStaging` / `stopStaging` (a staging protects the workspace it releases to), `releaseWorkspace`, `rollbackWorkspace` (a plan first, `releasePlanRefusalLines`), `workspaceHistory`, `getRepositoryReleaseSettings`, (5) Secrets, schedules and task configs (`putSecret`, `listSecrets`, `setSchedule`, `setCompute`, `setTimeout`), (6) Records' history and backups (`recordAudit`, `createRecordBackup`, `restoreRecordBackup`) and feedback (`listFeedback`, `closeFeedback`)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @elaraai/e3-cloud-client
|
|
7
|
+
|
|
8
|
+
The e3 cloud API's client: every call takes the deployment's origin
|
|
9
|
+
(`https://e3.example.com`) and request options holding a token, and
|
|
10
|
+
throws `ApiError` on a refusal, its `code` naming it. Values are East values in
|
|
11
|
+
BEAST2 on the wire, typed by `@elaraai/e3-cloud-types`, so a role or a
|
|
12
|
+
response is a variant (`variant('owner', null)`, `response.type`). e3's own
|
|
13
|
+
routes (repositories, packages, workspaces, datasets, runs) are
|
|
14
|
+
`@elaraai/e3-api-client`'s.
|
|
15
|
+
|
|
16
|
+
## Before writing code — search the example index
|
|
17
|
+
|
|
18
|
+
Every call has an entry in the plugin's index. Before writing code against a
|
|
19
|
+
deployment:
|
|
20
|
+
|
|
21
|
+
1. Call `search_e3_cloud_examples` with what
|
|
22
|
+
you are about to do (`deploy an app from code`, `release with a plan`).
|
|
23
|
+
Summaries come back first.
|
|
24
|
+
2. Fetch the one or two that match with
|
|
25
|
+
`get_e3_cloud_example` and pattern your code
|
|
26
|
+
on them.
|
|
27
|
+
3. Do not read `node_modules/@elaraai/**` or reason from `.d.ts` signatures:
|
|
28
|
+
the index holds the same calls, exact and far cheaper.
|
|
29
|
+
|
|
30
|
+
Nothing is injected for you; the search is the step.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { variant } from '@elaraai/east';
|
|
36
|
+
import { ApiError, addUser, whoami } from '@elaraai/e3-cloud-client';
|
|
37
|
+
|
|
38
|
+
const url = 'https://e3.example.com';
|
|
39
|
+
const options = { token: process.env.E3_TOKEN! };
|
|
40
|
+
|
|
41
|
+
const me = await whoami(url, options);
|
|
42
|
+
try {
|
|
43
|
+
await addUser(url, 'acme', { email: 'ada@example.com', role: variant('user', { roles: ['All apps'] }) }, options);
|
|
44
|
+
} catch (err) {
|
|
45
|
+
if (err instanceof ApiError) console.error(err.code); // forbidden, not_found, …
|
|
46
|
+
else throw err;
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Apps and releases
|
|
51
|
+
|
|
52
|
+
- An app deploy uploads the app object (`appUpload`, with
|
|
53
|
+
`@elaraai/e3-cloud-ui`'s `encodeAppObject`), then deploys it
|
|
54
|
+
(`appDeploy`). It answers `refused` with every problem, `checked` for a dry
|
|
55
|
+
run, `live`, `staged`, or `deploying` naming the deploy job its package runs
|
|
56
|
+
in, which `appDeployWait` waits for.
|
|
57
|
+
- A staging (`addStaging(url, repo, live, { name, start, plan })`, `start`
|
|
58
|
+
`variant('copy', null)` or `variant('as_is', null)`) protects the workspace
|
|
59
|
+
it releases to: its package and apps then change only by a release from it,
|
|
60
|
+
or a rollback; an app deploy or removal there throws `workspace_protected`
|
|
61
|
+
unless an admin passes `force`. `stopStaging` (admins) lifts it.
|
|
62
|
+
- A release (`releaseWorkspace(url, repo, target, { from, carry, removeApps, plan })`,
|
|
63
|
+
`from` the target's staging) answers `planned`, `refused` (its problems and
|
|
64
|
+
checks in the plan, `nothing_to_release` among them), `released` (its apps
|
|
65
|
+
switched) or `releasing` (the job `appDeployWait` waits for). Ask for the
|
|
66
|
+
plan first and show it; `releasePlanRefusalLines` says why a plan refuses,
|
|
67
|
+
and its `undoes` lists forced changes it undoes. `rollbackWorkspace` takes
|
|
68
|
+
an entry of `workspaceHistory`.
|
|
69
|
+
|
|
70
|
+
## Traps
|
|
71
|
+
|
|
72
|
+
- The URL is the deployment's origin, not `…/api`: the client adds the path.
|
|
73
|
+
- A refusal of a release or an app deploy is an answer (`refused`), not a
|
|
74
|
+
throw; a request the server cannot take at all throws `ApiError`.
|
|
75
|
+
- The version is the @elaraai lockstep: use the client of the release the
|
|
76
|
+
deployment runs.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: e3-cloud-ui
|
|
3
|
+
description: "Apps for e3 cloud — a solution's pages and menu, deployed to a workspace apart from its package and drawn natively by the e3-cloud web app. Use when: (1) Writing an app's pages with Page(name, meta, thunk) — the thunk returning the body, an East.function returning UIComponentType whose one argument is the page's params — or Page.task(name, uiTask, meta) for a ui() task's output, (2) Linking pages with PageLink (to, params) and Nav.go / Nav.back, (3) Declaring the sidebar with Menu.group and the app with App(name, { package, title, logo, home, menu, pages }), (4) Building the bundle an app deploy uploads with buildApp / exportApp, and reading a refusal (AppBuildError) or a deploy's problems, (5) Checking an app against a package with checkApp (@elaraai/e3-cloud-ui/check), (6) Reading an app's East types (AppType, PageType, AppBundleType — @elaraai/e3-cloud-ui/types), (7) Deploying with the e3-cloud CLI: app build, app deploy (UI-only, or with its package), app list / versions / remove."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# e3-cloud-ui — apps for e3 cloud
|
|
7
|
+
|
|
8
|
+
An **app** is a solution's pages and menu. It is deployed to one workspace of a
|
|
9
|
+
hosted e3, apart from the package, and the e3-cloud web app draws it natively:
|
|
10
|
+
each app is a sidebar section, each page a URL, its crumbs its parents. Apps
|
|
11
|
+
share a workspace's data, functions and records; staging and production each
|
|
12
|
+
have their own.
|
|
13
|
+
|
|
14
|
+
Read `README.md` for the author's guide; this file is the short form.
|
|
15
|
+
|
|
16
|
+
## Before writing code — search the example index
|
|
17
|
+
|
|
18
|
+
Every e3 cloud API has an example in the plugin's index: the page bodies of
|
|
19
|
+
`@elaraai/e3-cloud-ui`, and the hand-written entries for `App`, `Page`,
|
|
20
|
+
`Page.task`, `Menu`, `buildApp` and `checkApp`. A page's body is East and
|
|
21
|
+
e3-ui code, whose examples are the East plugin's. Before writing or changing
|
|
22
|
+
an app:
|
|
23
|
+
|
|
24
|
+
1. Call `search_e3_cloud_examples` for the
|
|
25
|
+
part of the app you are about to write. Summaries come back first: id,
|
|
26
|
+
description and keywords, a few hundred bytes each.
|
|
27
|
+
2. Fetch the one or two that match with
|
|
28
|
+
`get_e3_cloud_example` and pattern your code
|
|
29
|
+
on them.
|
|
30
|
+
3. For what a body does with data and components (`Data.bind`, `Func.bind`,
|
|
31
|
+
`Record.bind`, east-ui's components), search East's index too, with the
|
|
32
|
+
East plugin's `search_east_examples` (package `e3-ui` or `east-ui`).
|
|
33
|
+
4. Do not read `node_modules/@elaraai/**` or `*.examples.tsx` files
|
|
34
|
+
wholesale, and do not reason from `.d.ts` signatures: the index holds the
|
|
35
|
+
same code, exact and far cheaper.
|
|
36
|
+
|
|
37
|
+
Nothing is injected for you; the search is the step.
|
|
38
|
+
|
|
39
|
+
## Write a page
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { East, NullType } from '@elaraai/east';
|
|
43
|
+
import { Reactive, Stat, Slider, UIComponentType, VStack } from '@elaraai/east-ui';
|
|
44
|
+
import { Data } from '@elaraai/e3-ui';
|
|
45
|
+
import { App, Menu, Nav, Page, PageLink } from '@elaraai/e3-cloud-ui';
|
|
46
|
+
|
|
47
|
+
const overview = Page('overview', { title: 'Overview', icon: 'gauge-high' },
|
|
48
|
+
() => East.function([], UIComponentType, _$ => (
|
|
49
|
+
<Reactive>{$ => {
|
|
50
|
+
const t = $.let(Data.bind(target));
|
|
51
|
+
return (
|
|
52
|
+
<VStack>
|
|
53
|
+
<Stat label="Target" value={East.print(t.read())} />
|
|
54
|
+
<Slider value={t.read()} onChangeEnd={t.write} />
|
|
55
|
+
<PageLink to={line} params={{ site: 'North', line: 'L4' }}>North L4</PageLink>
|
|
56
|
+
</VStack>
|
|
57
|
+
);
|
|
58
|
+
}}</Reactive>
|
|
59
|
+
)));
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- The body is a **thunk**, `() => East.function(…)`: pages link both ways, so
|
|
63
|
+
bodies are built when the app builds.
|
|
64
|
+
- The function's **one argument is the page's params** (or none). Never write
|
|
65
|
+
the type separately: TypeScript takes it from the function.
|
|
66
|
+
- Bind data exactly as a `ui()` body does: `Data.bind`, `Data.bindPaged`,
|
|
67
|
+
`Func.bind`, `Record.bind`. Pass the defs, never names.
|
|
68
|
+
- `meta.parent` makes the crumbs and lights the menu item.
|
|
69
|
+
- Bind event handlers once: `const go = $.const(East.function([], NullType, $ => { $(Nav.go(line, key)); }))`.
|
|
70
|
+
|
|
71
|
+
## Declare the app
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
export default App('ops', {
|
|
75
|
+
package: acme, title: 'Acme Operations', home: overview,
|
|
76
|
+
menu: [Menu.group('Analyse', [overview, lines])],
|
|
77
|
+
pages: [overview, lines, line],
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`home` and menu pages take no params. `pages` lists every page.
|
|
82
|
+
|
|
83
|
+
## Build and deploy
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
e3-cloud app build src/apps/ops.tsx -o dist/ops.app
|
|
87
|
+
e3-cloud app deploy <repo-url> <workspace> dist/ops.app [--dry-run]
|
|
88
|
+
e3-cloud app deploy <repo-url> <workspace> --from-source src/apps/ops.tsx [--dry-run]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
An app is developed in the cloud, not locally: deploy it to a workspace of
|
|
92
|
+
your own (never a protected one: develop against its staging) and open it in
|
|
93
|
+
the console. `--dry-run` checks it against the workspace's package and changes
|
|
94
|
+
nothing; a deploy prints every problem when it is refused.
|
|
95
|
+
|
|
96
|
+
`buildApp` refuses an app that doesn't fit its own package (`AppBuildError`,
|
|
97
|
+
one line per problem). A deploy is UI-only when the workspace runs the bundle's
|
|
98
|
+
package, else it deploys the package too; both are refused unless every app
|
|
99
|
+
on the workspace fits.
|
|
100
|
+
|
|
101
|
+
## Traps
|
|
102
|
+
|
|
103
|
+
- A body written without the thunk can only link to pages defined above it.
|
|
104
|
+
- A page that writes a task's output or a record through `Data.bind` is
|
|
105
|
+
refused: write inputs; change records through their mutations.
|
|
106
|
+
- `Page.task` needs a task in the `ui` role (`ui()`), and its output shows only
|
|
107
|
+
after the workspace's next dataflow run.
|
|
108
|
+
- The version is the @elaraai lockstep: use the same version as east and e3.
|