@elaraai/e3-cloud-codex-plugin 1.0.97 → 1.1.1
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 +9 -9
- package/.build/mcp/server.js +33 -23
- package/.codex-plugin/plugin.json +1 -1
- package/index.json +257 -21
- package/package.json +1 -1
- package/skills/e3-cloud-cli/SKILL.md +31 -11
- package/skills/e3-cloud-client/SKILL.md +61 -3
- package/skills/e3-cloud-files/SKILL.md +81 -13
- package/skills/e3-cloud-ui/SKILL.md +11 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
1
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/codex-hook.js
|
|
2
2
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
3
3
|
import { existsSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { join, resolve as resolve3 } from "node:path";
|
|
7
7
|
|
|
8
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
8
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/codex-tools.js
|
|
9
9
|
import { resolve } from "node:path";
|
|
10
10
|
function patchFiles(command, cwd) {
|
|
11
11
|
const files = [];
|
|
@@ -43,7 +43,7 @@ function shellReadPaths(command, cwd) {
|
|
|
43
43
|
return [...paths];
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
46
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/bash-writes.js
|
|
47
47
|
import { resolve as resolve2 } from "node:path";
|
|
48
48
|
function isRealPath(token) {
|
|
49
49
|
if (token === "" || token.startsWith("&"))
|
|
@@ -92,7 +92,7 @@ function writtenPaths(command, cwd) {
|
|
|
92
92
|
return [...found];
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
95
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/transcript.js
|
|
96
96
|
import { readFile } from "node:fs/promises";
|
|
97
97
|
var SEARCH_TOOLS = ["mcp__plugin_east_east__search_east_examples", "mcp__plugin_east_east__get_east_example", "mcp__east__search_east_examples", "mcp__east__get_east_example"];
|
|
98
98
|
async function searchedInTranscript(transcriptPath, tools = SEARCH_TOOLS) {
|
|
@@ -105,7 +105,7 @@ async function searchedInTranscript(transcriptPath, tools = SEARCH_TOOLS) {
|
|
|
105
105
|
return tools.some((tool) => raw.includes(`"name":"${tool}"`) || raw.includes(`"name": "${tool}"`));
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
108
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/search-guidance.js
|
|
109
109
|
var EAST_GUIDANCE = {
|
|
110
110
|
searchTool: "mcp__plugin_east_east__search_east_examples",
|
|
111
111
|
getTool: "mcp__plugin_east_east__get_east_example",
|
|
@@ -147,7 +147,7 @@ var GATE_TEXT = gateText(EAST_GUIDANCE);
|
|
|
147
147
|
var READ_TEXT = readText(EAST_GUIDANCE);
|
|
148
148
|
var isExampleCorpusRead = corpusReadFor(EAST_GUIDANCE.scope);
|
|
149
149
|
|
|
150
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
150
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/codex-hook.js
|
|
151
151
|
function codexToolCall(event) {
|
|
152
152
|
const cwd = event.cwd || process.cwd();
|
|
153
153
|
const input = event.tool_input ?? {};
|
|
@@ -199,7 +199,7 @@ async function codexSearchGate(event, options, call = codexToolCall(event)) {
|
|
|
199
199
|
return context.length > 0 ? { decision: "context", text: context.join("\n\n") } : null;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
202
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/host.js
|
|
203
203
|
import { existsSync as existsSync2 } from "node:fs";
|
|
204
204
|
import { fileURLToPath } from "node:url";
|
|
205
205
|
var isCodex = existsSync2(fileURLToPath(new URL("../../.codex-plugin/plugin.json", import.meta.url)));
|
|
@@ -207,7 +207,7 @@ function hostText(text) {
|
|
|
207
207
|
return isCodex ? text.replaceAll("mcp__plugin_east_east__", "").replaceAll("/east:", "$east-codex-plugin:").replaceAll("Claude Code", "Codex") : text;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
210
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/hook-io.js
|
|
211
211
|
async function readHookInput() {
|
|
212
212
|
let input = "";
|
|
213
213
|
for await (const chunk of process.stdin) {
|
|
@@ -235,7 +235,7 @@ function writeHookDecision(hookEventName, decision, reason) {
|
|
|
235
235
|
process.stdout.write(JSON.stringify(output));
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
238
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/search-hooks.js
|
|
239
239
|
function writeSearchHookReply(hookEventName, reply) {
|
|
240
240
|
if (reply.decision === "deny")
|
|
241
241
|
writeHookDecision(hookEventName, "deny", reply.text);
|
package/.build/mcp/server.js
CHANGED
|
@@ -15140,7 +15140,7 @@ function object(shape, params) {
|
|
|
15140
15140
|
return new ZodMiniObject(def);
|
|
15141
15141
|
}
|
|
15142
15142
|
|
|
15143
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
15143
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
15144
15144
|
function isZ4Schema(s) {
|
|
15145
15145
|
const schema = s;
|
|
15146
15146
|
return !!schema._zod;
|
|
@@ -15995,7 +15995,7 @@ function preprocess(fn, schema) {
|
|
|
15995
15995
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/external.js
|
|
15996
15996
|
config(en_default2());
|
|
15997
15997
|
|
|
15998
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
15998
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
|
|
15999
15999
|
var LATEST_PROTOCOL_VERSION = "2025-11-25";
|
|
16000
16000
|
var SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, "2025-06-18", "2025-03-26", "2024-11-05", "2024-10-07"];
|
|
16001
16001
|
var RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
|
|
@@ -17526,7 +17526,7 @@ var UrlElicitationRequiredError = class extends McpError {
|
|
|
17526
17526
|
}
|
|
17527
17527
|
};
|
|
17528
17528
|
|
|
17529
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
17529
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
|
|
17530
17530
|
function isTerminal(status) {
|
|
17531
17531
|
return status === "completed" || status === "failed" || status === "cancelled";
|
|
17532
17532
|
}
|
|
@@ -18815,7 +18815,7 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
18815
18815
|
return combined;
|
|
18816
18816
|
};
|
|
18817
18817
|
|
|
18818
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
18818
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
|
|
18819
18819
|
function mapMiniTarget(t) {
|
|
18820
18820
|
if (!t)
|
|
18821
18821
|
return "draft-7";
|
|
@@ -18857,7 +18857,7 @@ function parseWithCompat(schema, data) {
|
|
|
18857
18857
|
return result.data;
|
|
18858
18858
|
}
|
|
18859
18859
|
|
|
18860
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
18860
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
18861
18861
|
var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
|
|
18862
18862
|
var Protocol = class {
|
|
18863
18863
|
constructor(_options) {
|
|
@@ -19834,7 +19834,7 @@ function mergeCapabilities(base, additional) {
|
|
|
19834
19834
|
return result;
|
|
19835
19835
|
}
|
|
19836
19836
|
|
|
19837
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
19837
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
|
|
19838
19838
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
19839
19839
|
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
19840
19840
|
function createDefaultAjvInstance() {
|
|
@@ -19902,7 +19902,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
19902
19902
|
}
|
|
19903
19903
|
};
|
|
19904
19904
|
|
|
19905
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
19905
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
|
|
19906
19906
|
var ExperimentalServerTasks = class {
|
|
19907
19907
|
constructor(_server) {
|
|
19908
19908
|
this._server = _server;
|
|
@@ -20115,7 +20115,7 @@ var ExperimentalServerTasks = class {
|
|
|
20115
20115
|
}
|
|
20116
20116
|
};
|
|
20117
20117
|
|
|
20118
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
20118
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
20119
20119
|
function assertToolsCallTaskCapability(requests, method, entityName) {
|
|
20120
20120
|
if (!requests) {
|
|
20121
20121
|
throw new Error(`${entityName} does not support task creation (required for ${method})`);
|
|
@@ -20150,7 +20150,7 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
|
|
|
20150
20150
|
}
|
|
20151
20151
|
}
|
|
20152
20152
|
|
|
20153
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
20153
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
20154
20154
|
var Server = class extends Protocol {
|
|
20155
20155
|
/**
|
|
20156
20156
|
* Initializes this server with the given name and version information.
|
|
@@ -20521,7 +20521,7 @@ var Server = class extends Protocol {
|
|
|
20521
20521
|
}
|
|
20522
20522
|
};
|
|
20523
20523
|
|
|
20524
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
20524
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
|
|
20525
20525
|
var COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
|
|
20526
20526
|
function isCompletable(schema) {
|
|
20527
20527
|
return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
|
|
@@ -20535,7 +20535,7 @@ var McpZodTypeKind;
|
|
|
20535
20535
|
McpZodTypeKind2["Completable"] = "McpCompletable";
|
|
20536
20536
|
})(McpZodTypeKind || (McpZodTypeKind = {}));
|
|
20537
20537
|
|
|
20538
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
20538
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
|
|
20539
20539
|
var TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
|
|
20540
20540
|
function validateToolName(name) {
|
|
20541
20541
|
const warnings = [];
|
|
@@ -20593,7 +20593,7 @@ function validateAndWarnToolName(name) {
|
|
|
20593
20593
|
return result.isValid;
|
|
20594
20594
|
}
|
|
20595
20595
|
|
|
20596
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
20596
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
|
|
20597
20597
|
var ExperimentalMcpServerTasks = class {
|
|
20598
20598
|
constructor(_mcpServer) {
|
|
20599
20599
|
this._mcpServer = _mcpServer;
|
|
@@ -20608,7 +20608,7 @@ var ExperimentalMcpServerTasks = class {
|
|
|
20608
20608
|
}
|
|
20609
20609
|
};
|
|
20610
20610
|
|
|
20611
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
20611
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
20612
20612
|
function toolInputElementCount(value, max) {
|
|
20613
20613
|
let count = 0;
|
|
20614
20614
|
const stack = [value];
|
|
@@ -20657,6 +20657,15 @@ var McpServer = class {
|
|
|
20657
20657
|
this._promptHandlersInitialized = false;
|
|
20658
20658
|
this.server = new Server(serverInfo, options);
|
|
20659
20659
|
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
20660
|
+
if (options?.capabilities?.tools) {
|
|
20661
|
+
this.setToolRequestHandlers();
|
|
20662
|
+
}
|
|
20663
|
+
if (options?.capabilities?.resources) {
|
|
20664
|
+
this.setResourceRequestHandlers();
|
|
20665
|
+
}
|
|
20666
|
+
if (options?.capabilities?.prompts) {
|
|
20667
|
+
this.setPromptRequestHandlers();
|
|
20668
|
+
}
|
|
20660
20669
|
}
|
|
20661
20670
|
/**
|
|
20662
20671
|
* Access experimental features.
|
|
@@ -21440,10 +21449,10 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
21440
21449
|
}
|
|
21441
21450
|
};
|
|
21442
21451
|
|
|
21443
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
21452
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
21444
21453
|
import process from "node:process";
|
|
21445
21454
|
|
|
21446
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
21455
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
21447
21456
|
var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
21448
21457
|
var ReadBuffer = class {
|
|
21449
21458
|
constructor(options) {
|
|
@@ -21480,7 +21489,7 @@ function serializeMessage(message) {
|
|
|
21480
21489
|
return JSON.stringify(message) + "\n";
|
|
21481
21490
|
}
|
|
21482
21491
|
|
|
21483
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.
|
|
21492
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.32.2_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
21484
21493
|
var StdioServerTransport = class {
|
|
21485
21494
|
constructor(_stdin = process.stdin, _stdout = process.stdout, options) {
|
|
21486
21495
|
this._stdin = _stdin;
|
|
@@ -21547,7 +21556,7 @@ var StdioServerTransport = class {
|
|
|
21547
21556
|
}
|
|
21548
21557
|
};
|
|
21549
21558
|
|
|
21550
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
21559
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/search.js
|
|
21551
21560
|
import { readFile } from "node:fs/promises";
|
|
21552
21561
|
|
|
21553
21562
|
// ../../node_modules/.pnpm/minisearch@7.2.0/node_modules/minisearch/dist/es/index.js
|
|
@@ -23360,7 +23369,7 @@ var objectToNumericMapAsync = async (object3) => {
|
|
|
23360
23369
|
var wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
23361
23370
|
var SPACE_OR_PUNCTUATION = /[\n\r\p{Z}\p{P}]+/u;
|
|
23362
23371
|
|
|
23363
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
23372
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/search-guidance.js
|
|
23364
23373
|
var EAST_GUIDANCE = {
|
|
23365
23374
|
searchTool: "mcp__plugin_east_east__search_east_examples",
|
|
23366
23375
|
getTool: "mcp__plugin_east_east__get_east_example",
|
|
@@ -23402,7 +23411,7 @@ var GATE_TEXT = gateText(EAST_GUIDANCE);
|
|
|
23402
23411
|
var READ_TEXT = readText(EAST_GUIDANCE);
|
|
23403
23412
|
var isExampleCorpusRead = corpusReadFor(EAST_GUIDANCE.scope);
|
|
23404
23413
|
|
|
23405
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
23414
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/search.js
|
|
23406
23415
|
var MIN_SCORE = 5;
|
|
23407
23416
|
async function loadIndexes(indexPaths) {
|
|
23408
23417
|
const entries = [];
|
|
@@ -23444,6 +23453,7 @@ function normalizePackage(filter, scopes = EAST_SCOPES) {
|
|
|
23444
23453
|
const scope = scopes.find((s) => name.startsWith(`${s.toLowerCase()}/`));
|
|
23445
23454
|
return scope === void 0 ? name : name.slice(scope.length + 1);
|
|
23446
23455
|
}
|
|
23456
|
+
var OPT_IN_PACKAGES = /* @__PURE__ */ new Set(["east-values"]);
|
|
23447
23457
|
function searchExamples(index, request) {
|
|
23448
23458
|
const known = index.packages;
|
|
23449
23459
|
const filter = request.package;
|
|
@@ -23453,7 +23463,7 @@ function searchExamples(index, request) {
|
|
|
23453
23463
|
}
|
|
23454
23464
|
const options = {
|
|
23455
23465
|
limit: request.limit,
|
|
23456
|
-
|
|
23466
|
+
filter: (r) => OPT_IN_PACKAGES.has(r.package) ? r.package === pkg : pkg === void 0 || r.package === pkg || r.skill === pkg
|
|
23457
23467
|
};
|
|
23458
23468
|
const hits = index.search.search(request.query, options);
|
|
23459
23469
|
return { entries: hits.filter((r) => r.score >= MIN_SCORE).slice(0, request.limit), known };
|
|
@@ -23527,7 +23537,7 @@ function getEntry(index, id) {
|
|
|
23527
23537
|
return stored === void 0 ? null : stored;
|
|
23528
23538
|
}
|
|
23529
23539
|
|
|
23530
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
23540
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/mcp/example-tools.js
|
|
23531
23541
|
var EAST_PACKAGES = ["east", "east-node-std", "east-node-io", "east-py-datascience", "east-ui", "e3-ui", "e3", "e3-ui-cli", "e3-create"];
|
|
23532
23542
|
function isLoaded(index) {
|
|
23533
23543
|
return typeof index.then === "function";
|
|
@@ -23548,7 +23558,7 @@ function registerExampleTools(server2, options) {
|
|
|
23548
23558
|
language: languageArg,
|
|
23549
23559
|
format: external_exports.enum(["summary", "full"]).default("summary").describe(`"summary" (default) lists the hits in one line each; "full" includes each hit's code in the requested language`),
|
|
23550
23560
|
limit: external_exports.number().int().min(1).max(20).default(5).describe("Maximum number of results to return (default 5, max 20)"),
|
|
23551
|
-
package: external_exports.string().optional().describe(`Filter results to one package by its bare name \u2014 ${packages.join(", ")} \u2014 ${scopesNamed}; an unknown name is reported with the indexed names`)
|
|
23561
|
+
package: external_exports.string().optional().describe(`Filter results to one package by its bare name \u2014 ${packages.join(", ")} \u2014 ${scopesNamed}; an unknown name is reported with the indexed names${packages.includes("east-values") ? '. "east-values" is east-py code working with East values directly (eager methods on python values, not an East function), and is searched only when named here' : ""}`)
|
|
23552
23562
|
}, async ({ query, language, format, limit, package: packageFilter }) => {
|
|
23553
23563
|
const index = await indexPromise;
|
|
23554
23564
|
const { entries, unknownPackage, known } = searchExamples(index, { query, limit, package: packageFilter, scopes });
|
|
@@ -23600,7 +23610,7 @@ function registerExampleTools(server2, options) {
|
|
|
23600
23610
|
import { fileURLToPath } from "node:url";
|
|
23601
23611
|
var E3_CLOUD_INDEX_PATH = fileURLToPath(new URL("../../index.json", import.meta.url));
|
|
23602
23612
|
|
|
23603
|
-
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.
|
|
23613
|
+
// ../../node_modules/.pnpm/@elaraai+east-plugin@1.0.101_typescript@5.9.3/node_modules/@elaraai/east-plugin/dist/lib/transcript.js
|
|
23604
23614
|
var SEARCH_TOOLS = ["mcp__plugin_east_east__search_east_examples", "mcp__plugin_east_east__get_east_example", "mcp__east__search_east_examples", "mcp__east__get_east_example"];
|
|
23605
23615
|
|
|
23606
23616
|
// ../e3-cloud-plugin/dist/lib/names.js
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "e3-cloud-codex-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "e3 cloud - apps for hosted e3 workspaces with @elaraai/e3-cloud-ui, files from buckets as inputs with @elaraai/e3-cloud-files, the e3-cloud CLI and @elaraai/e3-cloud-client: skills, example search and the search-first hooks",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Elara AI",
|
package/index.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 2,
|
|
3
3
|
"stats": {
|
|
4
|
-
"totalEntries":
|
|
4
|
+
"totalEntries": 47,
|
|
5
5
|
"totalFiles": 2,
|
|
6
6
|
"packages": {
|
|
7
7
|
"e3-cloud-ui": 12,
|
|
8
|
-
"e3-cloud-files":
|
|
9
|
-
"e3-cloud-cli":
|
|
10
|
-
"e3-cloud-client":
|
|
8
|
+
"e3-cloud-files": 14,
|
|
9
|
+
"e3-cloud-cli": 15,
|
|
10
|
+
"e3-cloud-client": 6
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
"entries": [
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
"package": "e3-cloud-ui",
|
|
184
184
|
"file": "packages/e3-cloud-ui/test/pages.examples.tsx",
|
|
185
185
|
"suite": "Functions and records",
|
|
186
|
-
"test": "Changing a record from a page: Record.bind(orders, [approve]) names the mutations the page may run, and o.mutate.approve(id) commits one",
|
|
186
|
+
"test": "Changing a record from a page: Record.bind(orders, ['approve']) names the mutations the page may run, by the names the record declares them under, and o.mutate.approve(id) commits one",
|
|
187
187
|
"keywords": [
|
|
188
188
|
"Record.bind",
|
|
189
189
|
"mutate",
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
"languages": [
|
|
204
204
|
"tsx"
|
|
205
205
|
],
|
|
206
|
-
"source": "// Changing a record from a page: Record.bind(orders, [approve]) names the mutations the page may run, and o.mutate.approve(id) commits one\n// inputs: []\n/** The runtime the package's functions run on. */\nconst RUNNER: Runner = { runtime: 'east-c', platforms: ['east-c-std'] };\n\nconst Order = StructType({ line: StringType, qty: FloatType, status: StringType });\n\n/** A record of orders, changed only through its mutations. */\nconst orders = e3.record('orders', DictType(StringType, Order), new Map())
|
|
206
|
+
"source": "// Changing a record from a page: Record.bind(orders, ['approve']) names the mutations the page may run, by the names the record declares them under, and o.mutate.approve(id) commits one\n// inputs: []\n/** The runtime the package's functions run on. */\nconst RUNNER: Runner = { runtime: 'east-c', platforms: ['east-c-std'] };\n\nconst Order = StructType({ line: StringType, qty: FloatType, status: StringType });\n\n/** A record of orders, changed only through its mutations, declared whole with its index and its mutation. */\nconst orders = e3.record('orders', DictType(StringType, Order), {\n initial: new Map(),\n indexes: (index) => ({\n /** The orders by line. */\n by_line: index.key(East.function([StringType, Order], StringType, (_$, _id, o) => o.line)),\n }),\n mutations: (mutation) => ({\n /** Approves an order by its id. */\n approve: mutation.reduce(\n East.function([DictType(StringType, Order), StringType], DictType(StringType, Order), (_$, all, _id) => all),\n { runner: RUNNER }),\n }),\n});\n\nEast.function([], UIComponentType, _$ => (\n <Reactive>{$ => {\n const o = $.let(Record.bind(orders, ['approve']));\n const approveA17 = $.const(East.function([], NullType, $ => { $(o.mutate.approve('A-17')); }));\n return <Button onClick={approveA17}>Approve A-17</Button>;\n }}</Reactive>\n ))"
|
|
207
207
|
},
|
|
208
208
|
{
|
|
209
209
|
"id": "e3-cloud-ui:pages.examples.tsx:pageReadsARecordThroughAnIndex",
|
|
@@ -211,11 +211,11 @@
|
|
|
211
211
|
"package": "e3-cloud-ui",
|
|
212
212
|
"file": "packages/e3-cloud-ui/test/pages.examples.tsx",
|
|
213
213
|
"suite": "Functions and records",
|
|
214
|
-
"test": "Reading a record through one of its indexes, a page at a time: Data.bindPaged(orders, { index:
|
|
214
|
+
"test": "Reading a record through one of its indexes, a page at a time: Data.bindPaged(orders, { index: 'by_line' }) given the name the record declares the index under, its rows the index key and the order's id",
|
|
215
215
|
"keywords": [
|
|
216
216
|
"Data.bindPaged",
|
|
217
217
|
"index",
|
|
218
|
-
"
|
|
218
|
+
"indexes",
|
|
219
219
|
"record",
|
|
220
220
|
"paged",
|
|
221
221
|
"Table",
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
"languages": [
|
|
233
233
|
"tsx"
|
|
234
234
|
],
|
|
235
|
-
"source": "// Reading a record through one of its indexes, a page at a time: Data.bindPaged(orders, { index:
|
|
235
|
+
"source": "// Reading a record through one of its indexes, a page at a time: Data.bindPaged(orders, { index: 'by_line' }) given the name the record declares the index under, its rows the index key and the order's id\n// inputs: []\n/** The runtime the package's functions run on. */\nconst RUNNER: Runner = { runtime: 'east-c', platforms: ['east-c-std'] };\n\nconst Order = StructType({ line: StringType, qty: FloatType, status: StringType });\n\n/** A record of orders, changed only through its mutations, declared whole with its index and its mutation. */\nconst orders = e3.record('orders', DictType(StringType, Order), {\n initial: new Map(),\n indexes: (index) => ({\n /** The orders by line. */\n by_line: index.key(East.function([StringType, Order], StringType, (_$, _id, o) => o.line)),\n }),\n mutations: (mutation) => ({\n /** Approves an order by its id. */\n approve: mutation.reduce(\n East.function([DictType(StringType, Order), StringType], DictType(StringType, Order), (_$, all, _id) => all),\n { runner: RUNNER }),\n }),\n});\n\nEast.function([], UIComponentType, _$ => (\n <Reactive>{$ => {\n const mine = $.let(Data.bindPaged(orders, { index: 'by_line' }));\n return <Table data={mine} columns={['ik', 'key']} />;\n }}</Reactive>\n ))"
|
|
236
236
|
},
|
|
237
237
|
{
|
|
238
238
|
"id": "e3-cloud-files:decode.examples.ts:fileAsJson",
|
|
@@ -314,6 +314,34 @@
|
|
|
314
314
|
],
|
|
315
315
|
"source": "// A text file input's lines, trimmed, blank ones left out\n// inputs: [utf8('first\\n\\n second \\nthird\\n')] returns: ['first', 'second', 'third']\nEast.function([BlobType], ArrayType(StringType), (_$, file) =>\n file.decodeUtf8().split('\\n').map((_$, line) => line.trim()).filter((_$, line) => line.notEquals('')))"
|
|
316
316
|
},
|
|
317
|
+
{
|
|
318
|
+
"id": "e3-cloud-files:decode.examples.ts:typedFileAsItsValue",
|
|
319
|
+
"skill": "e3-cloud-files",
|
|
320
|
+
"package": "e3-cloud-files",
|
|
321
|
+
"file": "packages/e3-cloud-files/test/decode.examples.ts",
|
|
322
|
+
"suite": "A typed file: no decoding",
|
|
323
|
+
"test": "A typed input needs no decoding: what upload.file('prices', { key: 'prices.beast2', type: ArrayType(Price) }) fills is the beast2 file's value itself, an Array<Price> the task takes as any dataset, here counted",
|
|
324
|
+
"keywords": [
|
|
325
|
+
"Files",
|
|
326
|
+
"typed",
|
|
327
|
+
"type",
|
|
328
|
+
"beast2",
|
|
329
|
+
"file",
|
|
330
|
+
"latest",
|
|
331
|
+
"no decoding",
|
|
332
|
+
"ArrayType",
|
|
333
|
+
"size",
|
|
334
|
+
"task"
|
|
335
|
+
],
|
|
336
|
+
"imports": [
|
|
337
|
+
"import { East, ArrayType, BlobType, DateTimeType, FloatType, IntegerType, StringType, StructType, example } from '@elaraai/east';",
|
|
338
|
+
"import { FilesFolderType, FilesListingType } from '@elaraai/e3-cloud-files';"
|
|
339
|
+
],
|
|
340
|
+
"languages": [
|
|
341
|
+
"typescript"
|
|
342
|
+
],
|
|
343
|
+
"source": "// A typed input needs no decoding: what upload.file('prices', { key: 'prices.beast2', type: ArrayType(Price) }) fills is the beast2 file's value itself, an Array<Price> the task takes as any dataset, here counted\n// inputs: [[{ sku: 'A1', price: 1.5 }, { sku: 'B2', price: 2.25 }, { sku: 'C3', price: 9 }]] returns: 3n\nconst Price = StructType({ sku: StringType, price: FloatType });\n\nEast.function([ArrayType(Price)], IntegerType, (_$, prices) => prices.size())"
|
|
344
|
+
},
|
|
317
345
|
{
|
|
318
346
|
"id": "e3-cloud-files:decode.examples.ts:folderAsOneArray",
|
|
319
347
|
"skill": "e3-cloud-files",
|
|
@@ -593,35 +621,104 @@
|
|
|
593
621
|
]
|
|
594
622
|
},
|
|
595
623
|
{
|
|
596
|
-
"id": "e3-cloud-files:static:typed",
|
|
624
|
+
"id": "e3-cloud-files:static:typed-input",
|
|
597
625
|
"skill": "e3-cloud-files",
|
|
598
626
|
"package": "e3-cloud-files",
|
|
599
627
|
"file": "static",
|
|
600
628
|
"suite": "Files",
|
|
601
|
-
"test": "A beast2 file as an input of its type with no task in between
|
|
629
|
+
"test": "A beast2 file as an input of its type with no task in between: file or latest with a type, a collection of any size, its header checked before any other byte, a file of another type refused naming both types, the same bytes under a new ETag changing nothing",
|
|
602
630
|
"keywords": [
|
|
603
631
|
"Files",
|
|
604
632
|
"type",
|
|
605
633
|
"beast2",
|
|
606
634
|
"typed",
|
|
635
|
+
"typed input",
|
|
607
636
|
"ArrayType",
|
|
608
637
|
"upload.file",
|
|
609
638
|
"upload.latest",
|
|
610
|
-
"upload.mutation",
|
|
611
|
-
"mutation",
|
|
612
|
-
"feed",
|
|
613
|
-
"record",
|
|
614
|
-
"e3.mutation.reduce",
|
|
615
639
|
"encodeBeast2For",
|
|
640
|
+
"Beast2ElementWriter",
|
|
616
641
|
"collection",
|
|
642
|
+
"type_mismatch",
|
|
643
|
+
"not_beast2",
|
|
617
644
|
"e3-cloud-files"
|
|
618
645
|
],
|
|
619
646
|
"imports": [
|
|
620
|
-
"import { East, ArrayType,
|
|
647
|
+
"import { East, ArrayType, FloatType, IntegerType, StringType, StructType } from '@elaraai/east';",
|
|
621
648
|
"import e3, { type Runner } from '@elaraai/e3';",
|
|
622
649
|
"import { Files } from '@elaraai/e3-cloud-files';"
|
|
623
650
|
],
|
|
624
|
-
"source": "// src/package.ts\nconst Price = StructType({ sku: StringType, price: FloatType });\
|
|
651
|
+
"source": "// src/package.ts\nconst Price = StructType({ sku: StringType, price: FloatType });\nexport const upload = Files.source('upload');\n// A beast2 file of Array<Price> (encodeBeast2For(ArrayType(Price)), a Beast2ElementWriter for a collection of any size, east-py, e3 convert):\n// an input of that type, taken in as the value it holds, its header checked before any other byte is read; a file of another type is\n// refused naming both types (type_mismatch), no beast2 at all as not_beast2, and the input keeps its value. The same bytes again under\n// a new ETag give the same value: nothing downstream runs\nexport const prices = upload.file('prices', { key: 'prices.beast2', type: ArrayType(Price) });\nexport const stock = upload.latest('stock', { prefix: 'stock/', include: '*.beast2', type: ArrayType(Price) }); // the greatest key, typed\nconst runner: Runner = { runtime: 'east-c', platforms: ['east-c-std'] };\n// Used as any dataset: no decoding, the value is the file's\nexport const summary = e3.task('price_summary', [prices, stock], East.function([ArrayType(Price), ArrayType(Price)], IntegerType, (_$, rows, latest) => rows.size().add(latest.size())), { runner });\nexport default e3.package('typed', '1.0.0', summary);\n\n// src/files.ts\nexport default Files.manifest([upload]);",
|
|
652
|
+
"languages": [
|
|
653
|
+
"typescript"
|
|
654
|
+
]
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
"id": "e3-cloud-files:static:record-seed",
|
|
658
|
+
"skill": "e3-cloud-files",
|
|
659
|
+
"package": "e3-cloud-files",
|
|
660
|
+
"file": "static",
|
|
661
|
+
"suite": "Files",
|
|
662
|
+
"test": "A record seeded from a file: upload.record(name, type, spec, parts) is e3.record(name, type, parts) with no initial value, declared whole with its indexes, mutations and migrations, pending until its file arrives (its first state, $init), seeded again by a changed file while nothing has mutated it since ($seed) or on --reset, kept once mutated; the tasks over it wait meanwhile, and its history names the file",
|
|
663
|
+
"keywords": [
|
|
664
|
+
"Files",
|
|
665
|
+
"record",
|
|
666
|
+
"seed",
|
|
667
|
+
"seeded",
|
|
668
|
+
"upload.record",
|
|
669
|
+
"pending",
|
|
670
|
+
"$init",
|
|
671
|
+
"$seed",
|
|
672
|
+
"--reset",
|
|
673
|
+
"genesis",
|
|
674
|
+
"no initial value",
|
|
675
|
+
"e3.record",
|
|
676
|
+
"declared whole",
|
|
677
|
+
"mutations",
|
|
678
|
+
"kept",
|
|
679
|
+
"waiting",
|
|
680
|
+
"e3-cloud-files"
|
|
681
|
+
],
|
|
682
|
+
"imports": [
|
|
683
|
+
"import { East, DictType, IntegerType, StringType, StructType } from '@elaraai/east';",
|
|
684
|
+
"import e3, { type Runner } from '@elaraai/e3';",
|
|
685
|
+
"import { Files } from '@elaraai/e3-cloud-files';"
|
|
686
|
+
],
|
|
687
|
+
"source": "// src/package.ts\nconst Customer = StructType({ name: StringType, tier: IntegerType });\nconst CustomerBook = DictType(StringType, Customer);\nexport const upload = Files.source('upload');\n// e3.record('customers', CustomerBook, parts) with no initial value: pending until customers.beast2 arrives, which is its first state ($init:\n// nothing runs on an empty state first, and the tasks over it wait as on an unset input, the run completing without them); a changed\n// file while nothing has mutated it since is its state again ($seed); once mutated it is kept, until `files sync --reset customers`\n// (or `files push --reset customers`) takes the file as its state over whatever was done. The workspace page shows it Pending, its page\n// what seeds it, `files status` prints pending; its history reads \"Initialised from customers.beast2 (2 rows)\" and \"Seeded again from …\"\n// Declared whole, as any record is: its indexes, mutations and migrations are the fourth argument, as e3.record takes them (an initial\n// value there is refused). Its mutations are any record's: after one, the file no longer seeds it until a reset\nexport const customers = upload.record('customers', CustomerBook, { key: 'customers.beast2' }, {\n mutations: (mutation) => ({\n set_tier: mutation.reduce(East.function([CustomerBook, StringType, IntegerType], CustomerBook, ($, state, key, tier) => {\n const next = $.let(state.copy());\n $(next.insertOrUpdate(key, { name: key, tier }, (_$, existing, _given) => ({ name: existing.name, tier })));\n return next;\n })),\n }),\n});\nconst runner: Runner = { runtime: 'east-c', platforms: ['east-c-std'] };\nexport const customerCount = e3.task('customer_count', [customers], East.function([CustomerBook], IntegerType, (_$, book) => book.size()), { runner });\n// The record carries its mutation: the package takes the task over it\nexport default e3.package('typed', '1.0.0', customerCount);\n\n// src/files.ts\nexport default Files.manifest([upload]);\n\n// A deploy that cannot keep the record (its type changed) under --schema reset unassigns it: pending again, seeded by the next\n// version's file once the new declarations are deployed",
|
|
688
|
+
"languages": [
|
|
689
|
+
"typescript"
|
|
690
|
+
]
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
"id": "e3-cloud-files:static:mutation-feed",
|
|
694
|
+
"skill": "e3-cloud-files",
|
|
695
|
+
"package": "e3-cloud-files",
|
|
696
|
+
"file": "static",
|
|
697
|
+
"suite": "Files",
|
|
698
|
+
"test": "A record's mutation fed by files: upload.mutation(def, spec), def one the record declares (priceBook.mutations.load_prices), applies each new file the spec selects, in key order, once by its bytes' hash, as the mutation's one argument; a refused file is tried again only once it changes, a feed of a pending record waits, and each commit names its file",
|
|
699
|
+
"keywords": [
|
|
700
|
+
"Files",
|
|
701
|
+
"mutation",
|
|
702
|
+
"feed",
|
|
703
|
+
"fed",
|
|
704
|
+
"upload.mutation",
|
|
705
|
+
"mutation.reduce",
|
|
706
|
+
"mutations",
|
|
707
|
+
"one argument",
|
|
708
|
+
"idempotent",
|
|
709
|
+
"once per file",
|
|
710
|
+
"key order",
|
|
711
|
+
"refused",
|
|
712
|
+
"waiting",
|
|
713
|
+
"deltas",
|
|
714
|
+
"e3-cloud-files"
|
|
715
|
+
],
|
|
716
|
+
"imports": [
|
|
717
|
+
"import { East, ArrayType, DictType, FloatType, StringType, StructType } from '@elaraai/east';",
|
|
718
|
+
"import e3 from '@elaraai/e3';",
|
|
719
|
+
"import { Files } from '@elaraai/e3-cloud-files';"
|
|
720
|
+
],
|
|
721
|
+
"source": "// src/package.ts\nconst Price = StructType({ sku: StringType, price: FloatType });\nconst PriceBook = DictType(StringType, FloatType);\nexport const upload = Files.source('upload');\n// A record the app's users edit, declared whole with a mutation of one argument that loads a delivery into it: the record's own\n// reduce (or edit; a patch cannot be fed), its rules deciding what a delivery does. A delivery holding a price below zero is refused\n// whole: the mutation fails, the book is kept, and the file is tried again only once it changes, the files after it waiting\nexport const priceBook = e3.record('price_book', PriceBook, {\n initial: new Map(),\n mutations: (mutation) => ({\n load_prices: mutation.reduce(East.function([PriceBook, ArrayType(Price)], PriceBook, ($, state, rows) => {\n const next = $.let(state.copy()); // the book as it is (a mutation's state is immutable), each delivered price over its sku's\n $.for(rows, ($, row) => {\n $.if(row.price.lessThan(0), ($) => $.error(East.str`a price below zero: ${row.sku}`));\n $(next.insertOrUpdate(row.sku, row.price, (_$, _existing, delivered) => delivered));\n });\n return next;\n })),\n }),\n});\n// The record carries its mutation: the package takes the record\nexport default e3.package('typed', '1.0.0', priceBook);\n\n// src/files.ts: each new delta file under deltas/ calls load_prices once with its value, by the file's hash (a sync run again\n// applies nothing twice; the same bytes under another name are applied no more); a feed of a record with no state yet waits for\n// it; a sync seeds records before it feeds mutations. The commit reads in the record's history as any mutation's, through the\n// files channel, naming the file it was fed\nupload.mutation(priceBook.mutations.load_prices, { prefix: 'deltas/', include: '*.beast2' });\nexport default Files.manifest([upload]);",
|
|
625
722
|
"languages": [
|
|
626
723
|
"typescript"
|
|
627
724
|
]
|
|
@@ -661,7 +758,7 @@
|
|
|
661
758
|
"package": "e3-cloud-cli",
|
|
662
759
|
"file": "static",
|
|
663
760
|
"suite": "e3-cloud",
|
|
664
|
-
"test": "Signing in to a deployment, and who you are there: the e3 CLI's sign-in (`e3 auth login`; there is no `e3 login`), whose credentials the e3-cloud CLI shares",
|
|
761
|
+
"test": "Signing in to a deployment, and who you are there: the e3 CLI's sign-in (`e3 auth login`; there is no `e3 login`), whose credentials the e3-cloud CLI shares; whoami names the e3 cloud release and e3 the deployment runs beside this CLI's",
|
|
665
762
|
"keywords": [
|
|
666
763
|
"login",
|
|
667
764
|
"sign in",
|
|
@@ -674,7 +771,36 @@
|
|
|
674
771
|
"e3-cloud"
|
|
675
772
|
],
|
|
676
773
|
"imports": [],
|
|
677
|
-
"source": "npm install -g @elaraai/e3-cloud-cli @elaraai/e3-cli\ne3 auth login https://e3.example.com # the device flow; e3-cloud reads the same credentials\ne3-cloud whoami https://e3.example.com # your identity there,
|
|
774
|
+
"source": "npm install -g @elaraai/e3-cloud-cli @elaraai/e3-cli\ne3 auth login https://e3.example.com # the device flow; e3-cloud reads the same credentials\ne3-cloud whoami https://e3.example.com # your identity there, whether you are an admin, and the releases (e3-cloud --version, below)",
|
|
775
|
+
"languages": [
|
|
776
|
+
"typescript"
|
|
777
|
+
]
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
"id": "e3-cloud-cli:static:versions",
|
|
781
|
+
"skill": "e3-cloud-cli",
|
|
782
|
+
"package": "e3-cloud-cli",
|
|
783
|
+
"file": "static",
|
|
784
|
+
"suite": "e3-cloud --version / whoami",
|
|
785
|
+
"test": "Which releases a push or a deploy depends on: this CLI's e3 cloud release and the east and e3 it is built with (--version, --json), and the deployment's release and e3 (whoami), with a note where their e3s differ: a package exported with a newer e3 than the deployment's is refused",
|
|
786
|
+
"keywords": [
|
|
787
|
+
"version",
|
|
788
|
+
"--version",
|
|
789
|
+
"-V",
|
|
790
|
+
"--json",
|
|
791
|
+
"whoami",
|
|
792
|
+
"release",
|
|
793
|
+
"e3 version",
|
|
794
|
+
"east version",
|
|
795
|
+
"deployment",
|
|
796
|
+
"platform",
|
|
797
|
+
"lockstep",
|
|
798
|
+
"compatible",
|
|
799
|
+
"staged for",
|
|
800
|
+
"e3-cloud"
|
|
801
|
+
],
|
|
802
|
+
"imports": [],
|
|
803
|
+
"source": "e3-cloud --version # e3-cloud 1.1.1 (east 1.0.101, e3 1.0.101): this CLI, and the east and e3 it is built with\ne3-cloud --version --json # {\"e3Cloud\":\"1.1.1\",\"east\":\"1.0.101\",\"e3\":\"1.0.101\"}\ne3-cloud whoami https://e3.example.com\n# sub: … email: … admin: false\n# deployment: e3-cloud 1.1.1, e3 1.0.101\n# staged for: e3 1.0.102 (apps deployed with --for-platform) (only when a bundle is staged for a next e3)\n# cli: e3-cloud 1.1.1 (east 1.0.101, e3 1.0.101)\n# note: … only where the CLI's e3 and the deployment's differ: a package exported with a newer e3 than the deployment's is refused\n# A project builds with the e3 cloud release the deployment runs, beside the east and e3 it pins (npm view @elaraai/e3-cloud-files@1.1.1 peerDependencies)",
|
|
678
804
|
"languages": [
|
|
679
805
|
"typescript"
|
|
680
806
|
]
|
|
@@ -909,7 +1035,10 @@
|
|
|
909
1035
|
"restore",
|
|
910
1036
|
"backup-pull",
|
|
911
1037
|
"commit",
|
|
912
|
-
"audit"
|
|
1038
|
+
"audit",
|
|
1039
|
+
"pending",
|
|
1040
|
+
"$seed",
|
|
1041
|
+
"seeded from a file"
|
|
913
1042
|
],
|
|
914
1043
|
"imports": [],
|
|
915
1044
|
"source": "e3-cloud records list https://e3.example.com/repos/acme production\ne3-cloud records history https://e3.example.com/repos/acme production orders --limit 50\ne3-cloud records show https://e3.example.com/repos/acme production orders <commit> -o orders.beast2\ne3-cloud records backup https://e3.example.com/repos/acme production orders --note \"before the import\"\ne3-cloud records rollback https://e3.example.com/repos/acme production orders <commit> # a new commit holding that state",
|
|
@@ -990,6 +1119,7 @@
|
|
|
990
1119
|
"beast2",
|
|
991
1120
|
"typed",
|
|
992
1121
|
"unchanged",
|
|
1122
|
+
"dataset",
|
|
993
1123
|
"e3-cloud"
|
|
994
1124
|
],
|
|
995
1125
|
"imports": [],
|
|
@@ -998,6 +1128,42 @@
|
|
|
998
1128
|
"typescript"
|
|
999
1129
|
]
|
|
1000
1130
|
},
|
|
1131
|
+
{
|
|
1132
|
+
"id": "e3-cloud-cli:static:files-push-dataset",
|
|
1133
|
+
"skill": "e3-cloud-cli",
|
|
1134
|
+
"package": "e3-cloud-cli",
|
|
1135
|
+
"file": "static",
|
|
1136
|
+
"suite": "e3-cloud files",
|
|
1137
|
+
"test": "Pushing a workspace's dataset (a task's output, an input or a record) into a source as the file of its value, with no file kept by hand: dataset:<workspace>.<name>, read from the repository --from names (a local path or a repository URL), matched by its name or --as, unchanged for the same stored value, refused in its row when unassigned or not found; a seed's history names the dataset",
|
|
1138
|
+
"keywords": [
|
|
1139
|
+
"files",
|
|
1140
|
+
"push",
|
|
1141
|
+
"dataset",
|
|
1142
|
+
"dataset:",
|
|
1143
|
+
"--from",
|
|
1144
|
+
"task output",
|
|
1145
|
+
"input",
|
|
1146
|
+
"record",
|
|
1147
|
+
"seed",
|
|
1148
|
+
"$seed",
|
|
1149
|
+
"--reset",
|
|
1150
|
+
"--as",
|
|
1151
|
+
"unchanged",
|
|
1152
|
+
"unassigned",
|
|
1153
|
+
"not_found",
|
|
1154
|
+
"local repository",
|
|
1155
|
+
"local workspace",
|
|
1156
|
+
"e3 dataset get",
|
|
1157
|
+
"beast2",
|
|
1158
|
+
"e3-dataset",
|
|
1159
|
+
"e3-cloud"
|
|
1160
|
+
],
|
|
1161
|
+
"imports": [],
|
|
1162
|
+
"source": "# A local workspace's task output seeding a deployed workspace's record: matched by its name (record:customers), put at its mapping's key\ne3-cloud files push https://e3.example.com/repos/acme dev dataset:dev.customers --from ./archive\n# dataset:dev.customers (task output) → record:customers seed 3 MiB put $init #1 12,004 rows\ne3-cloud files push https://e3.example.com/repos/acme dev dataset:dev.customers --from ./archive # the same stored value again: unchanged\ne3 dataflow run ./archive dev # its value changes\ne3-cloud files push https://e3.example.com/repos/acme dev dataset:dev.customers --from ./archive # $seed #2 while nothing has mutated the record; kept once something has\ne3-cloud files push https://e3.example.com/repos/acme dev dataset:dev.customers --from ./archive --reset customers # its state again, over its mutations\n# --from defaults as e3's [repo] does ($E3_REPO, then .); a repository URL reads a deployed workspace's dataset with your e3 login\ne3-cloud files push ./repo dev dataset:production.price_list --from https://e3.example.com/repos/acme --as prices # any file or latest mapping, by --as\n# Its bytes are the value's beast2, as `e3 dataset get -f beast2` writes it, read a segment at a time and checked against the mapping's type\n# before anything is put; under a latest prefix it is put as <name>.beast2; a folder or a listing takes no dataset. Refused in its row, the\n# rest going on: unassigned (a task output not produced since the last deploy, an input never set, a record with no state), not_found, ambiguous.\n# The object carries e3-dataset and e3-dataset-hash metadata; the history reads\n# \"Initialised from customers.beast2 (12,004 rows), from dev.customers at 3f9a2b1c4d5e\"",
|
|
1163
|
+
"languages": [
|
|
1164
|
+
"typescript"
|
|
1165
|
+
]
|
|
1166
|
+
},
|
|
1001
1167
|
{
|
|
1002
1168
|
"id": "e3-cloud-client:static:basics",
|
|
1003
1169
|
"skill": "e3-cloud-client",
|
|
@@ -1023,6 +1189,32 @@
|
|
|
1023
1189
|
"typescript"
|
|
1024
1190
|
]
|
|
1025
1191
|
},
|
|
1192
|
+
{
|
|
1193
|
+
"id": "e3-cloud-client:static:versions",
|
|
1194
|
+
"skill": "e3-cloud-client",
|
|
1195
|
+
"package": "e3-cloud-client",
|
|
1196
|
+
"file": "static",
|
|
1197
|
+
"suite": "@elaraai/e3-cloud-client platform",
|
|
1198
|
+
"test": "Which releases a deployment runs, from code: its e3 cloud release, the e3 its platform and runners run, and each next e3 an app's bundle is staged for; null from a deployment that predates it",
|
|
1199
|
+
"keywords": [
|
|
1200
|
+
"platformVersions",
|
|
1201
|
+
"PlatformVersions",
|
|
1202
|
+
"version",
|
|
1203
|
+
"release",
|
|
1204
|
+
"e3 version",
|
|
1205
|
+
"e3Cloud",
|
|
1206
|
+
"staged",
|
|
1207
|
+
"deployment",
|
|
1208
|
+
"/api/platform"
|
|
1209
|
+
],
|
|
1210
|
+
"imports": [
|
|
1211
|
+
"import { platformVersions } from '@elaraai/e3-cloud-client';"
|
|
1212
|
+
],
|
|
1213
|
+
"source": "const versions = await platformVersions(url, options); // anyone signed in may ask\nif (versions === null) console.log('the deployment predates it: it names no release');\nelse {\n console.log(versions.e3Cloud.type === 'some' ? versions.e3Cloud.value : 'release not stated', versions.e3, versions.staged.join(', '));\n // A package exported with a newer e3 than versions.e3 is refused: build with the e3 cloud release the deployment runs\n}",
|
|
1214
|
+
"languages": [
|
|
1215
|
+
"typescript"
|
|
1216
|
+
]
|
|
1217
|
+
},
|
|
1026
1218
|
{
|
|
1027
1219
|
"id": "e3-cloud-client:static:app-deploy",
|
|
1028
1220
|
"skill": "e3-cloud-client",
|
|
@@ -1109,6 +1301,50 @@
|
|
|
1109
1301
|
"languages": [
|
|
1110
1302
|
"typescript"
|
|
1111
1303
|
]
|
|
1304
|
+
},
|
|
1305
|
+
{
|
|
1306
|
+
"skill": "e3-cloud-client",
|
|
1307
|
+
"package": "e3-cloud-client",
|
|
1308
|
+
"file": "static",
|
|
1309
|
+
"id": "e3-cloud-client:static:files",
|
|
1310
|
+
"suite": "@elaraai/e3-cloud-client files",
|
|
1311
|
+
"test": "Files from code: deploy a workspace's declarations, bind a source, sync named targets (a seeded record reset) and wait for the sync's report, read what each mapping holds, and push a file from disk (plan, upload through the platform, sync), or a workspace's dataset as the file of its value",
|
|
1312
|
+
"keywords": [
|
|
1313
|
+
"getFiles",
|
|
1314
|
+
"deployFiles",
|
|
1315
|
+
"bindFilesSource",
|
|
1316
|
+
"startFilesSync",
|
|
1317
|
+
"filesSyncWait",
|
|
1318
|
+
"planFilesPush",
|
|
1319
|
+
"completeFilesPush",
|
|
1320
|
+
"FilesPushBytes",
|
|
1321
|
+
"uploadFilesPush",
|
|
1322
|
+
"FilesTarget",
|
|
1323
|
+
"targets",
|
|
1324
|
+
"reset",
|
|
1325
|
+
"pending",
|
|
1326
|
+
"seeded",
|
|
1327
|
+
"record",
|
|
1328
|
+
"mutation",
|
|
1329
|
+
"push",
|
|
1330
|
+
"dataset",
|
|
1331
|
+
"unchanged",
|
|
1332
|
+
"refused",
|
|
1333
|
+
"retaken",
|
|
1334
|
+
"workspace_protected"
|
|
1335
|
+
],
|
|
1336
|
+
"imports": [
|
|
1337
|
+
"import { createReadStream } from 'node:fs';",
|
|
1338
|
+
"import { stat } from 'node:fs/promises';",
|
|
1339
|
+
"import { none, some, variant } from '@elaraai/east';",
|
|
1340
|
+
"import { bindFilesSource, deployFiles, filesSyncWait, getFiles, planFilesPush, startFilesSync, uploadFilesPush, type FilesPushBytes } from '@elaraai/e3-cloud-client';",
|
|
1341
|
+
"import { filesPushRefusalText, filesTargetText } from '@elaraai/e3-cloud-types';",
|
|
1342
|
+
"import manifest from './files.js'; // export default Files.manifest([upload])"
|
|
1343
|
+
],
|
|
1344
|
+
"source": "// The declarations (checked against the package the workspace runs), then where the source's files are\nconst deployed = await deployFiles(url, 'acme', 'staging', manifest, options);\nif (deployed.type === 'refused') throw new Error(deployed.value.problems.map((p) => p.type).join(', '));\nawait bindFilesSource(url, 'acme', 'staging', { source: 'upload', url: 's3://partner-drop/acme/', region: none, profile: none, latest: none }, options);\n\n// A sync of two targets: the seeded record's file taken as its state again (reset), and the fed mutation's new files\nconst start = await startFilesSync(url, 'acme', 'staging', {\n targets: [variant('record', 'customers'), variant('mutation', { record: 'price_book', mutation: 'load_prices' })],\n reset: ['customers'],\n}, options);\nconst id = start.value; // started, or running: the sync under way, waited on the same way\nconst job = await filesSyncWait(url, 'acme', 'staging', id, options, { deadlineMs: 10 * 60_000 });\nfor (const m of job.report.type === 'some' ? job.report.value.mappings : []) {\n console.log(filesTargetText(m.target), m.updated ? `written (commit ${m.commit.type === 'some' ? m.commit.value.slice(0, 12) : 'none'})` : 'as it was', m.refused.length === 0 ? '' : `refused ${m.refused[0]!.key}`);\n}\n\n// What each mapping holds now; a record not yet seeded is pending\nconst files = await getFiles(url, 'acme', 'staging', options);\nconsole.log(files.status.mappings.map((m) => `${filesTargetText(m.target)}: ${m.pending ? 'pending' : m.holds.type === 'some' ? m.holds.value.key : 'nothing yet'}`).join(' · '));\n\n// A push from disk: the plan says per file where it goes and how to upload it; uploadFilesPush puts it through the platform\n// (one PUT bound to its SHA-256, or a multipart upload it completes), then one sync of the targets put\nconst path = 'data/customers.beast2';\nconst size = (await stat(path)).size;\nconst plan = await planFilesPush(url, 'acme', 'staging', {\n files: [{ name: 'customers.beast2', directory: none, size: BigInt(size), sha256, type: some(customerBookType), dataset: none }], // sha256: hex; type: its beast2 header's\n as: none,\n}, options);\nconst bytes: FilesPushBytes = { size, ranged: true, read: (start) => createReadStream(path, { start }) }; // a file reads from any offset\nfor (const f of plan.files) {\n if (f.outcome.type === 'refused') console.warn(f.name, filesPushRefusalText(f.outcome.value));\n else if (f.outcome.type === 'put') await uploadFilesPush(url, 'acme', 'staging', plan, f.outcome.value, bytes, options); // an `external` put throws: your own credentials\n}\nawait startFilesSync(url, 'acme', 'staging', { targets: plan.files.flatMap((f) => (f.outcome.type === 'put' ? [f.outcome.value.target] : [])) }, options);\n// A workspace's dataset is offered as the file of its value: dataset: some({ workspace: 'dev', name: 'customers', hash }), its type the value's,\n// its bytes the value's beast2 as `e3 dataset get -f beast2` writes it, streamed (ranged: false: never held whole) and matched by its name.\n// `e3-cloud files push … dataset:dev.customers --from <repo>` does all of it",
|
|
1345
|
+
"languages": [
|
|
1346
|
+
"typescript"
|
|
1347
|
+
]
|
|
1112
1348
|
}
|
|
1113
1349
|
]
|
|
1114
1350
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elaraai/e3-cloud-codex-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "e3 cloud - apps for hosted e3 workspaces with @elaraai/e3-cloud-ui, files from buckets as inputs with @elaraai/e3-cloud-files, the e3-cloud CLI and @elaraai/e3-cloud-client: skills, example search and the search-first hooks",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
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)
|
|
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), checking who you are and which e3 cloud release and e3 the deployment runs (`e3-cloud whoami SERVER`), and which this CLI is built with (`e3-cloud --version`, `--json`), (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… See the detailed scope below."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## Detailed skill scope
|
|
7
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)
|
|
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), checking who you are and which e3 cloud release and e3 the deployment runs (`e3-cloud whoami SERVER`), and which this CLI is built with (`e3-cloud --version`, `--json`), (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` (a release carries the package, the apps and the Files declarations; the target keeps its data and bindings), `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 …`), (8) Files — a solution's inputs from files in a bucket: `e3-cloud files deploy|bind|sync|push|status`, given a local repository's path or a repository URL, and `files push` of files from disk or of a workspace's dataset as the file of its value (`dataset:WORKSPACE.NAME`, `--from` a local repository or a URL) (the e3-cloud-files skill declares and decodes them), (9) Walking a solution through its life, step by step — starting it, adding a staging, developing an app's pages, changing the package's tasks and inputs, migrating a record, Files, rehearsing and releasing, rolling back, an emergency change to production, people and roles, schedules, secrets and compute, feedback, the platform's next e3, and retiring an app or a workspace.
|
|
9
9
|
|
|
10
10
|
# e3-cloud — the e3 cloud CLI (@elaraai/e3-cloud-cli)
|
|
11
11
|
|
|
@@ -42,7 +42,7 @@ Nothing is injected for you; the search is the step.
|
|
|
42
42
|
```bash
|
|
43
43
|
npm install -g @elaraai/e3-cloud-cli @elaraai/e3-cli
|
|
44
44
|
e3 auth login https://e3.example.com
|
|
45
|
-
e3-cloud whoami https://e3.example.com
|
|
45
|
+
e3-cloud whoami https://e3.example.com # you, the release and e3 the deployment runs, and this CLI's
|
|
46
46
|
|
|
47
47
|
# An app: build its bundle, check it, deploy it
|
|
48
48
|
e3-cloud app build src/apps/ops.tsx
|
|
@@ -163,9 +163,9 @@ e3 dataflow run URL staging
|
|
|
163
163
|
|
|
164
164
|
### 5. Migrate a record
|
|
165
165
|
|
|
166
|
-
A record's new type comes with a migration in
|
|
167
|
-
`
|
|
168
|
-
|
|
166
|
+
A record's new type comes with a migration in its own declaration: a step
|
|
167
|
+
added at the end of its `migrations` (`migration.value`, `rows` or `rekey`,
|
|
168
|
+
each named, the list's order the chain; the e3 skill). Then, in staging:
|
|
169
169
|
|
|
170
170
|
```bash
|
|
171
171
|
e3-cloud records backup URL staging orders --note "before orders v2"
|
|
@@ -193,6 +193,9 @@ e3-cloud release URL staging production --plan
|
|
|
193
193
|
e3-cloud files deploy URL staging src/files.ts
|
|
194
194
|
e3-cloud files bind URL staging upload s3://bucket/acme/staging/
|
|
195
195
|
e3-cloud files sync URL staging
|
|
196
|
+
e3-cloud files push URL staging ./data/prices.beast2 ./data/customers.beast2 # from disk: matched by name (or --as), put, synced
|
|
197
|
+
e3-cloud files push URL staging dataset:dev.customers --from ./repo # a local workspace's dataset, as the file of its value
|
|
198
|
+
e3-cloud files sync URL staging --target record:customers --reset customers # named targets; a seeded record's file as its state again
|
|
196
199
|
e3 dataflow run URL staging
|
|
197
200
|
```
|
|
198
201
|
|
|
@@ -317,8 +320,9 @@ e3-cloud app deploy URL staging --from-source src/apps/ops.tsx --for-platform 1.
|
|
|
317
320
|
e3-cloud release URL staging production
|
|
318
321
|
```
|
|
319
322
|
|
|
320
|
-
- Build with the
|
|
321
|
-
live app: it goes live when the
|
|
323
|
+
- Build with the e3 cloud release built with the next e3 (its packages pin
|
|
324
|
+
it) and stage the bundle beside the live app: it goes live when the
|
|
325
|
+
platform moves to that e3. A release
|
|
322
326
|
carries staging's staged bundles, so production gets them through its
|
|
323
327
|
staging.
|
|
324
328
|
|
|
@@ -413,8 +417,18 @@ a repository URL:
|
|
|
413
417
|
changes them, and a source may be bound before a release brings the
|
|
414
418
|
declarations that read it.
|
|
415
419
|
- `files sync <repo> <ws>` reads only files whose ETag or size changed and
|
|
416
|
-
writes only inputs whose files changed; `--
|
|
420
|
+
writes only inputs whose files changed; `--target`, `--reset`, `--dry-run`. It doesn't
|
|
417
421
|
run the dataflow: `e3 dataflow run` does, and the sync prints the command.
|
|
422
|
+
- `files push <repo> <ws> <path…>` puts files from disk, or datasets
|
|
423
|
+
(`dataset:<ws>.<name>`: a task's output, an input or a record, read from
|
|
424
|
+
the repository `--from` names, a local path or a URL, default `$E3_REPO`
|
|
425
|
+
then `.`), into the source each one's mapping reads, then syncs what was
|
|
426
|
+
put: matched by name or `--as`, checked against the mapping's type before
|
|
427
|
+
anything is put, `unchanged` when the source holds it already, refused in
|
|
428
|
+
its row otherwise (`unassigned`, `not_found`, `no_mapping`, `type_mismatch`,
|
|
429
|
+
…); `--reset`, `--dry-run`, `--profile` (a bucket the platform doesn't
|
|
430
|
+
write). A seed's or feed's history names the file, and the dataset it was
|
|
431
|
+
pushed from.
|
|
418
432
|
- `files status <repo> <ws>`: the declarations, the bindings, the last sync.
|
|
419
433
|
|
|
420
434
|
## Traps
|
|
@@ -431,5 +445,11 @@ a repository URL:
|
|
|
431
445
|
hasn't bound: bind it in the target first.
|
|
432
446
|
- `secrets set` reads the value from stdin unless `--value` is given; the
|
|
433
447
|
next run reads the new value.
|
|
434
|
-
- The version is
|
|
435
|
-
deployment runs
|
|
448
|
+
- The version is e3 cloud's own, not e3's: use the CLI of the e3 cloud
|
|
449
|
+
release your deployment runs, beside e3's CLI of the e3 that release is
|
|
450
|
+
built with (its dependencies pin it). `e3-cloud --version` prints
|
|
451
|
+
`e3-cloud 1.1.1 (east 1.0.101, e3 1.0.101)` (`--json`:
|
|
452
|
+
`{"e3Cloud":…,"east":…,"e3":…}`); `e3-cloud whoami <server>` prints the
|
|
453
|
+
deployment's `deployment: e3-cloud 1.1.1, e3 1.0.101` beside it, and a
|
|
454
|
+
`note:` where the e3s differ: a package exported with a newer e3 than the
|
|
455
|
+
deployment's is refused.
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
---
|
|
2
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
|
|
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`,… See the detailed scope below."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
## Detailed skill scope
|
|
7
|
+
|
|
8
|
+
@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`), (7) Files from code — `getFiles`, `deployFiles`, `bindFilesSource`, `startFilesSync` and `filesSyncWait`, and a push: `planFilesPush`, `uploadFilesPush` (a file from disk by ranges, or a workspace's dataset as its value streams, with its type and where it came from), `completeFilesPush`, (8) Which releases a deployment runs (`platformVersions`: its e3 cloud release, its e3, the next e3s bundles are staged for).
|
|
9
|
+
|
|
6
10
|
# @elaraai/e3-cloud-client
|
|
7
11
|
|
|
8
12
|
The e3 cloud API's client: every call takes the deployment's origin
|
|
@@ -67,10 +71,64 @@ try {
|
|
|
67
71
|
and its `undoes` lists forced changes it undoes. `rollbackWorkspace` takes
|
|
68
72
|
an entry of `workspaceHistory`.
|
|
69
73
|
|
|
74
|
+
## Files
|
|
75
|
+
|
|
76
|
+
- `getFiles(url, repo, ws, options)` answers a workspace's Files: its
|
|
77
|
+
declarations (`manifest`), where each source is bound (`bindings`), the
|
|
78
|
+
last sync, a sync under way, and `status` — per mapping, what it holds and
|
|
79
|
+
whether its record is `pending` (seeded from a file, its file not yet
|
|
80
|
+
arrived).
|
|
81
|
+
- `deployFiles(url, repo, ws, manifest, options `{ dryRun?, force? }`)` deploys declarations
|
|
82
|
+
(`Files.manifest(...)` from `@elaraai/e3-cloud-files`): `deployed` with
|
|
83
|
+
the targets the next sync takes again whole (`retaken`), `checked` for a
|
|
84
|
+
dry run, or `refused` with every problem. A workspace with a staging
|
|
85
|
+
refuses it (`workspace_protected`) unless an admin forces it.
|
|
86
|
+
- `bindFilesSource(url, repo, ws, binding, options)` says where a source's
|
|
87
|
+
files are (`s3://bucket/prefix/`): `bound` with what the next sync takes
|
|
88
|
+
again, or `refused` (a bucket the deployment does not let the repository
|
|
89
|
+
bind). Bindings are each workspace's own; a release never changes them.
|
|
90
|
+
- `startFilesSync(url, repo, ws, { dryRun?, targets?, reset? }, options)`
|
|
91
|
+
answers `started` with the sync's id, or `running` with the one under way;
|
|
92
|
+
`filesSyncWait(url, repo, ws, id, options, { deadlineMs?, refresh?, signal? })`
|
|
93
|
+
polls it to its end and answers the job, its `report` per target (what was
|
|
94
|
+
taken, the commit a seed or feed made, what was refused and why, what
|
|
95
|
+
waits). `targets` are `variant('input', name)`, `variant('record', name)`
|
|
96
|
+
or `variant('mutation', { record, mutation })`; `reset` names seeded
|
|
97
|
+
records whose file is taken as their state again.
|
|
98
|
+
- `planFilesPush(url, repo, ws, { files, as }, options)` plans a push of
|
|
99
|
+
files (each offered with its name, size, SHA-256 and beast2 header type,
|
|
100
|
+
and `dataset: some({ workspace, name, hash })` for a workspace's dataset
|
|
101
|
+
offered as the file of its value): per file `put` with its key and how to
|
|
102
|
+
upload it — `single` (one PUT with the plan's headers), `multipart` (a URL
|
|
103
|
+
per part, then a completion) or `external` (your own credentials) —
|
|
104
|
+
`unchanged`, or `refused` with why (`filesPushRefusalText`). A dataset is
|
|
105
|
+
matched by its name, to the `file` or `latest` mapping filling the input
|
|
106
|
+
or record of that name.
|
|
107
|
+
- `uploadFilesPush(url, repo, ws, plan, put, bytes, options, refresh?)`
|
|
108
|
+
uploads one put through the platform, `bytes` a `FilesPushBytes`
|
|
109
|
+
(`{ size, read(start), ranged }`): a file on disk is `ranged` (its parts
|
|
110
|
+
sent four at a time, each read from its start), a dataset's value streams
|
|
111
|
+
from its repository (`ranged: false`, parts one after another, never held
|
|
112
|
+
whole). A multipart upload is completed under the object's key in its
|
|
113
|
+
bucket (`completeFilesPush`); a source that throws as its bytes end (a
|
|
114
|
+
dataset rewritten while it was read) has its last bytes held back, so
|
|
115
|
+
nothing other than the planned bytes is ever stored. Then sync the targets
|
|
116
|
+
put. The CLI's `files push` does all of this.
|
|
117
|
+
|
|
118
|
+
## Versions
|
|
119
|
+
|
|
120
|
+
- `platformVersions(url, options)` answers what a deployment runs:
|
|
121
|
+
`{ e3Cloud: some('1.1.1'), e3: '1.0.101', staged: [...] }` (the next e3s
|
|
122
|
+
an app's bundle is staged for, in the repositories the caller manages), or
|
|
123
|
+
`null` from a deployment that predates it. A package exported with a newer
|
|
124
|
+
e3 than the deployment's is refused: compare it with the e3 your project
|
|
125
|
+
builds with before a deploy.
|
|
126
|
+
|
|
70
127
|
## Traps
|
|
71
128
|
|
|
72
129
|
- The URL is the deployment's origin, not `…/api`: the client adds the path.
|
|
73
130
|
- A refusal of a release or an app deploy is an answer (`refused`), not a
|
|
74
131
|
throw; a request the server cannot take at all throws `ApiError`.
|
|
75
|
-
- The version is
|
|
76
|
-
deployment
|
|
132
|
+
- The version is e3 cloud's own, shared by every e3 cloud package and
|
|
133
|
+
independent of e3's: use the client of the e3 cloud release the deployment
|
|
134
|
+
runs, beside the east and e3 it pins.
|
|
@@ -5,7 +5,7 @@ description: "Files for e3 cloud — a solution's inputs that come from files in
|
|
|
5
5
|
|
|
6
6
|
## Detailed skill scope
|
|
7
7
|
|
|
8
|
-
Files for e3 cloud — a solution's inputs that come from files in a bucket (s3://bucket/prefix/), declared in its code and synced when asked, the same on a local repository and a deployed workspace. Use when: (1) Declaring which inputs a bucket's files fill with Files.source(name) and its file, latest, folder and listing, then Files.manifest([...]) as a module's default export, (2) Decoding what arrives in a task: a Blob (file, latest), a Dict of path to Blob (folder) or a listing of sizes, times and ETags, as East's JSON, CSV or text, (3) Deploying the declarations to a workspace and binding each source to s3://bucket/prefix/ with e3-cloud files deploy and bind, (4) Syncing what changed with e3-cloud files sync, locally with your own cloud profile (--profile, --latest), then running the dataflow with e3 dataflow run, (5) Reading a refusal: declarations that don't fit the package (FilesDeclarationError, a deploy's problems), an unbound source, a file over its limit, a protected workspace (workspace_protected), (6) Moving declarations to production through staging: a release carries them with the package and apps, a rollback restores them, a copy brings bindings and what each input took, and production's bindings stay its own, (7) Reading Files' East types (FilesManifestType, FilesBindingType, FilesSyncReportType — @elaraai/e3-cloud-types), (8) Taking a beast2 file in as an input of its type with no task in between: file or latest with a type, a collection of any size, (9) Feeding a record's mutation from files with source.mutation(def, spec), each new file applied once, (10) Pushing files from disk into a source and taking them in with e3-cloud files push, matched by name or --as, dry-run, unchanged, (11) Syncing or resetting particular targets with --target and --reset.
|
|
8
|
+
Files for e3 cloud — a solution's inputs that come from files in a bucket (s3://bucket/prefix/), declared in its code and synced when asked, the same on a local repository and a deployed workspace. Use when: (1) Declaring which inputs a bucket's files fill with Files.source(name) and its file, latest, folder and listing, then Files.manifest([...]) as a module's default export, (2) Decoding what arrives in a task: a Blob (file, latest), a Dict of path to Blob (folder) or a listing of sizes, times and ETags, as East's JSON, CSV or text, (3) Deploying the declarations to a workspace and binding each source to s3://bucket/prefix/ with e3-cloud files deploy and bind, (4) Syncing what changed with e3-cloud files sync, locally with your own cloud profile (--profile, --latest), then running the dataflow with e3 dataflow run, (5) Reading a refusal: declarations that don't fit the package (FilesDeclarationError, a deploy's problems), an unbound source, a file over its limit, a protected workspace (workspace_protected), (6) Moving declarations to production through staging: a release carries them with the package and apps, a rollback restores them, a copy brings bindings and what each input took, and production's bindings stay its own, (7) Reading Files' East types (FilesManifestType, FilesBindingType, FilesSyncReportType — @elaraai/e3-cloud-types), (8) Taking a beast2 file in as an input of its type with no task in between: file or latest with a type, a collection of any size, (9) Feeding a record's mutation from files with source.mutation(def, spec), def one its record declares (priceBook.mutations.load_prices), each new file applied once, (10) Pushing files from disk into a source and taking them in with e3-cloud files push, matched by name or --as, dry-run, unchanged, or a workspace's dataset (a task's output, an input, a record) as the file of its value with dataset:workspace.name and --from, local or remote at either end, (11) Seeding a record from a file with source.record(name, type, spec, parts): e3.record with no initial value, declared whole with its indexes, mutations and migrations, pending until its file, its tasks waiting meanwhile, (12) Syncing or resetting particular targets with --target and --reset.
|
|
9
9
|
|
|
10
10
|
# e3-cloud-files — files as e3 inputs
|
|
11
11
|
|
|
@@ -15,8 +15,9 @@ are, a bucket and a prefix, and `e3-cloud files sync` brings in what changed:
|
|
|
15
15
|
on a local repository with your own cloud credentials, in the cloud with the
|
|
16
16
|
platform's read-only role. A file arrives as it is, a `Blob`, and a task
|
|
17
17
|
decodes it; or, named with a type, a beast2 file arrives as the value it
|
|
18
|
-
holds, with no task in between. `e3-cloud files push` puts files from disk
|
|
19
|
-
|
|
18
|
+
holds, with no task in between. `e3-cloud files push` puts files from disk,
|
|
19
|
+
or a workspace's datasets as the files of their values, into a source and
|
|
20
|
+
takes them in. Nothing polls: a sync runs when someone asks.
|
|
20
21
|
|
|
21
22
|
Read `README.md` for the author's guide; this file is the short form.
|
|
22
23
|
|
|
@@ -74,7 +75,8 @@ What do you need?
|
|
|
74
75
|
│ ├─ A beast2 file as its value → source.file(input, { key, type: ArrayType(Row) }) input: Array<Row>, no task between
|
|
75
76
|
│ ├─ The newest of a folder → source.latest(input, { prefix, include? }) input: Blob, the greatest key
|
|
76
77
|
│ ├─ The newest, typed → source.latest(input, { prefix, include?, type })
|
|
77
|
-
│ ├─
|
|
78
|
+
│ ├─ A record's first state → source.record(name, type, { key } | { prefix, include? }, parts?) e3.record(name, type, parts): pending until its file
|
|
79
|
+
│ ├─ Feed a record's mutation → source.mutation(record.mutations.<name>, { key } | { prefix, include? }) every new file, in key order, once
|
|
78
80
|
│ ├─ Every file of a folder → source.folder(input, { prefix, include? }) input: Dict<String, Blob> by path
|
|
79
81
|
│ ├─ A folder's files, not bytes → source.listing(input, { prefix, include? }) input: Dict<String, {size, modified, etag}>
|
|
80
82
|
│ ├─ Subfolders' files too → include: '**/*.csv' ('*.csv' is the top level only)
|
|
@@ -92,6 +94,7 @@ What do you need?
|
|
|
92
94
|
│ │ └─ Locally only → --profile <aws profile>, --latest <n> (each folder's n greatest keys)
|
|
93
95
|
│ ├─ Bring in what changed → e3-cloud files sync <repo> <ws> [--target t…] [--reset record…] [--dry-run]
|
|
94
96
|
│ ├─ Put files from disk → e3-cloud files push <repo> <ws> <file|dir>… [--as target] [--dry-run] [--profile p]
|
|
97
|
+
│ ├─ Push a workspace's dataset → e3-cloud files push <repo> <ws> dataset:<ws>.<name>… [--from <repo>] (a task's output, an input, a record)
|
|
95
98
|
│ ├─ What is declared, bound, held → e3-cloud files status <repo> <ws> (each mapping, its type, what it holds, pending)
|
|
96
99
|
│ └─ Run the dataflow on it → e3 dataflow run <repo> <ws> (a sync doesn't run it)
|
|
97
100
|
├─ Production: a workspace with a staging (a deployed repository's URL)
|
|
@@ -122,6 +125,9 @@ export const rates = upload.file('rates', { key: 'rates.json' });
|
|
|
122
125
|
export const stock = upload.latest('stock', { prefix: 'stock/', include: '*.json' }); // input: Blob, the greatest key
|
|
123
126
|
export const orders = upload.folder('orders', { prefix: 'orders/', include: '*.json' }); // input: Dict<String, Blob>
|
|
124
127
|
export const orderFiles = upload.listing('order_files', { prefix: 'orders/' }); // input: each file's size, modified, etag
|
|
128
|
+
export const prices = upload.file('prices', { key: 'prices.beast2', type: ArrayType(Price) }); // input: Array<Price>: the beast2 file's value, any size
|
|
129
|
+
export const customers = upload.record('customers', CustomerBook, { key: 'customers.beast2' }); // a record, e3.record('customers', CustomerBook): pending until its file
|
|
130
|
+
upload.mutation(priceBook.mutations.load_prices, { prefix: 'deltas/', include: '*.beast2' }); // each new delta file fed to the record's mutation, in key order
|
|
125
131
|
|
|
126
132
|
export default Files.manifest([upload]); // what e3-cloud files deploy deploys
|
|
127
133
|
```
|
|
@@ -131,9 +137,22 @@ export default Files.manifest([upload]); // what e3-cloud files deploy dep
|
|
|
131
137
|
`file` or `latest` with a `type` is an input of that type: the file must be
|
|
132
138
|
beast2 of it (`encodeBeast2For(T)`, east-py, `e3 convert`), a collection of
|
|
133
139
|
any size, checked by its header before any other byte is read.
|
|
134
|
-
- `source.
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
- `source.record(name, type, spec, parts?)` is `e3.record(name, type, parts)`
|
|
141
|
+
with no initial value. It is declared whole: its indexes, mutations and
|
|
142
|
+
migrations are `parts`, as `e3.record` takes them
|
|
143
|
+
(`{ mutations: (mutation) => ({ set_tier: mutation.reduce(fn) }) }`), and an
|
|
144
|
+
initial value is refused. It is pending until its file arrives, which is
|
|
145
|
+
its first state (`$init`; nothing runs on an empty state first, and the
|
|
146
|
+
tasks over it wait as on an unset input, the run completing without them).
|
|
147
|
+
A changed file while nothing has mutated it since is its state again
|
|
148
|
+
(`$seed`); mutated since, it is kept until `files sync --reset <record>`.
|
|
149
|
+
- `source.mutation(def, spec)` feeds a record's mutation: `def` is one the
|
|
150
|
+
record declares, `record.mutations.<name>`, a `reduce` or an `edit` taking
|
|
151
|
+
exactly one argument. Every new file the spec selects (one key, or each
|
|
152
|
+
under the prefix its glob matches) is applied in key order, once by its
|
|
153
|
+
bytes' hash, so the same bytes under another name are applied no more; a
|
|
154
|
+
file the mutation refuses holds the ones after it until it changes; a busy
|
|
155
|
+
record leaves the file to the next sync.
|
|
137
156
|
- Keys and prefixes are relative to where a workspace binds the source; a
|
|
138
157
|
prefix is `''` or ends with `/`.
|
|
139
158
|
- `include` is a glob over the path under the prefix: `*` within one folder,
|
|
@@ -162,7 +181,7 @@ file's path under the prefix, in path order.
|
|
|
162
181
|
e3-cloud files deploy <repo> <workspace> src/files.ts [--dry-run]
|
|
163
182
|
e3-cloud files bind <repo> <workspace> upload s3://bucket/prefix/ [--region r] [--profile p] [--latest n]
|
|
164
183
|
e3-cloud files sync <repo> <workspace> [--target name|record:r|mutation:r.m ...] [--reset record...] [--dry-run]
|
|
165
|
-
e3-cloud files push <repo> <workspace> <file|dir>... [--as target] [--reset record...] [--dry-run] [--profile p]
|
|
184
|
+
e3-cloud files push <repo> <workspace> <file|dir|dataset:ws.name>... [--from repo] [--as target] [--reset record...] [--dry-run] [--profile p]
|
|
166
185
|
e3-cloud files status <repo> <workspace>
|
|
167
186
|
e3 dataflow run <repo> <workspace>
|
|
168
187
|
```
|
|
@@ -172,7 +191,38 @@ name, a `latest` under its prefix, a directory to the `folder`; `--as` names
|
|
|
172
191
|
one), checks its type and size, puts it where the source is bound (the
|
|
173
192
|
platform signs the upload into the deployment's own bucket, bound to the
|
|
174
193
|
file's SHA-256; your own credentials elsewhere), then syncs what was put. A
|
|
175
|
-
file the source holds already is `unchanged
|
|
194
|
+
file the source holds already is `unchanged`; refused: `no_mapping`,
|
|
195
|
+
`ambiguous` (name the target with `--as`), `not_included` (the mapping's
|
|
196
|
+
glob leaves it out), `not_latest` (a greater key would shadow it), a typed
|
|
197
|
+
mapping's file of another type or no beast2, one over the limit. The report
|
|
198
|
+
numbers a record's seeds: `$init #1`, `$seed #2`, …
|
|
199
|
+
|
|
200
|
+
`dataset:<workspace>.<name>` pushes a value a workspace holds (a task's
|
|
201
|
+
output, an input or a record, by its name) as the file of its value would,
|
|
202
|
+
with no file kept by hand: its bytes are the value's beast2 (as
|
|
203
|
+
`e3 dataset get -f beast2` writes it), read a segment at a time from the
|
|
204
|
+
repository `--from` names (a local path or a repository URL; default
|
|
205
|
+
`$E3_REPO`, then `.`, as e3's `[repo]`). It goes to the `file` or `latest`
|
|
206
|
+
mapping filling the input or record of its name, else `--as` names one; it
|
|
207
|
+
is put at the `file`'s key, or under the `latest`'s prefix as
|
|
208
|
+
`<name>.beast2`; a `folder` or `listing` takes none. The same stored value
|
|
209
|
+
is `unchanged`; refused in their rows: `unassigned` (a task output not
|
|
210
|
+
produced since the workspace's last deploy, an input never set, a record
|
|
211
|
+
with no state), `not_found`, `ambiguous` (two of the workspace's datasets
|
|
212
|
+
have the name); a dataset a run rewrites while it uploads fails in its row
|
|
213
|
+
(push again). The object carries `e3-dataset` and `e3-dataset-hash`
|
|
214
|
+
metadata, and a seed's or feed's history names the dataset: "Initialised
|
|
215
|
+
from customers.beast2 (12,004 rows), from dev.customers at 3f9a2b1c4d5e".
|
|
216
|
+
Files, directories and datasets mix in one push.
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# A local workspace's task output, seeding a deployed workspace's record
|
|
220
|
+
e3-cloud files push https://e3.example.com/repos/acme dev dataset:dev.customers --from ./archive
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`--target` names an input, `record:<name>` or `mutation:<record>.<name>`
|
|
224
|
+
(split at its last dot); `--reset <record>` takes a seeded record's file as
|
|
225
|
+
its state again, whatever mutated it since.
|
|
176
226
|
|
|
177
227
|
`<repo>` is a local repository's path or a repository URL. Deploy the package
|
|
178
228
|
first (`e3 workspace deploy`), then the declarations, which are checked
|
|
@@ -193,9 +243,25 @@ keeps only each folder's n greatest keys.
|
|
|
193
243
|
(`type_mismatch` with both types, `not_beast2`): the input keeps its value.
|
|
194
244
|
A typed value that is no collection is at most 1 GiB; a collection's
|
|
195
245
|
segments at most 64 MiB (`segment_too_large`: write it again).
|
|
196
|
-
- A seeded record (`upload.record
|
|
197
|
-
|
|
198
|
-
|
|
246
|
+
- A seeded record (`upload.record(name, type, { key })`) is pending until
|
|
247
|
+
its file, which is its first state (`$init`); a changed file seeds it
|
|
248
|
+
again while unmutated (`$seed`), `--reset` does whatever was done since;
|
|
249
|
+
the tasks over it wait meanwhile. The workspace page shows it Pending, its
|
|
250
|
+
page says what seeds it, `files status` prints `pending`; its seeds read
|
|
251
|
+
"Initialised from customers.beast2 (12,004 rows)" / "Seeded again from …"
|
|
252
|
+
in its history (the record page, `e3-cloud records history`), a feed names
|
|
253
|
+
its file. A deploy that cannot keep it (its type changed) under
|
|
254
|
+
`--schema reset` unassigns it: pending again, seeded by the next version's
|
|
255
|
+
file.
|
|
256
|
+
- A dataset pushed to a seeded record seeds it like a file: again while
|
|
257
|
+
unmutated (`$seed #n`), `kept` once mutated, over its mutations with
|
|
258
|
+
`--reset`. A dataset whose value is unchanged since the last push is
|
|
259
|
+
`unchanged`, nothing put; one never produced since the workspace's last
|
|
260
|
+
deploy is `unassigned`: run the dataflow first.
|
|
261
|
+
- A record is declared whole: a fed mutation is one its record declares
|
|
262
|
+
(`priceBook.mutations.load_prices`), and a seeded record's indexes,
|
|
263
|
+
mutations and migrations are `upload.record`'s `parts`; an initial value
|
|
264
|
+
there is refused, its file being its first state.
|
|
199
265
|
- A file over 1 GiB less 64 KiB (`file`, `latest`), or over 64 MiB less
|
|
200
266
|
64 KiB in a folder, is refused and named in the report, never truncated.
|
|
201
267
|
So is a file the sync can't read (archived, under a key it may not use,
|
|
@@ -213,7 +279,9 @@ keeps only each folder's n greatest keys.
|
|
|
213
279
|
- Bindings never travel with a release; a copy carries them. A staging
|
|
214
280
|
started as a copy of production reads production's files until you bind it
|
|
215
281
|
elsewhere.
|
|
216
|
-
- The version is
|
|
282
|
+
- The version is e3 cloud's own, not e3's: install the release built with the
|
|
283
|
+
e3 the deployment runs, its peers (east, e3) at exactly the versions it
|
|
284
|
+
names, and the `e3-cloud` CLI of the same release.
|
|
217
285
|
|
|
218
286
|
## Related skills
|
|
219
287
|
|
|
@@ -64,7 +64,10 @@ const overview = Page('overview', { title: 'Overview', icon: 'gauge-high' },
|
|
|
64
64
|
- The function's **one argument is the page's params** (or none). Never write
|
|
65
65
|
the type separately: TypeScript takes it from the function.
|
|
66
66
|
- Bind data exactly as a `ui()` body does: `Data.bind`, `Data.bindPaged`,
|
|
67
|
-
`Func.bind`, `Record.bind`. Pass the defs, never
|
|
67
|
+
`Func.bind`, `Record.bind`. Pass the defs, never a dataset's or a
|
|
68
|
+
function's name; a record's mutations and indexes are named as the record
|
|
69
|
+
declares them: `Record.bind(orders, ['approve'])`,
|
|
70
|
+
`Data.bindPaged(orders, { index: 'by_line' })`.
|
|
68
71
|
- `meta.parent` makes the crumbs and lights the menu item.
|
|
69
72
|
- Bind event handlers once: `const go = $.const(East.function([], NullType, $ => { $(Nav.go(line, key)); }))`.
|
|
70
73
|
|
|
@@ -103,6 +106,12 @@ on the workspace fits.
|
|
|
103
106
|
- A body written without the thunk can only link to pages defined above it.
|
|
104
107
|
- A page that writes a task's output or a record through `Data.bind` is
|
|
105
108
|
refused: write inputs; change records through their mutations.
|
|
109
|
+
- A record is declared whole: its indexes, mutations and migrations in its
|
|
110
|
+
own `e3.record(name, type, { initial, indexes, mutations, migrations })`.
|
|
111
|
+
`e3.package` takes the record, never one of its parts.
|
|
106
112
|
- `Page.task` needs a task in the `ui` role (`ui()`), and its output shows only
|
|
107
113
|
after the workspace's next dataflow run.
|
|
108
|
-
- The version is
|
|
114
|
+
- The version is e3 cloud's own, not e3's: install the release built with the
|
|
115
|
+
e3 the deployment runs, its peers (east, east-ui, e3, e3-ui) at exactly the
|
|
116
|
+
versions it names. An app built with another e3 than the platform's is
|
|
117
|
+
refused, naming both.
|