@fieldwork-ai/cli 0.16.0 → 0.17.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/dist/commands/automations.js +20 -1
- package/dist/commands/tables.d.ts +2 -0
- package/dist/commands/tables.js +41 -0
- package/dist/http.js +9 -1
- package/dist/index.js +2 -0
- package/package.json +8 -7
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
1
2
|
import { api, apiJson, getContext, requireOrgId } from "../http.js";
|
|
2
3
|
import { EXIT, confirm, exitCodeFor, fail, note, printData } from "../output.js";
|
|
3
|
-
const TERMINAL_STATUSES = new Set(["succeeded", "failed"]);
|
|
4
|
+
const TERMINAL_STATUSES = new Set(["succeeded", "failed", "cancelled", "needs_attention"]);
|
|
4
5
|
async function resolveAutomation(name) {
|
|
5
6
|
const body = await apiJson(`/api/organizations/${requireOrgId()}/automations?name=${encodeURIComponent(name)}`);
|
|
6
7
|
const automation = body.automations?.[0];
|
|
@@ -70,6 +71,24 @@ async function followRun(automationId, runId, intervalSeconds, json) {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
export function registerAutomationCommands(program) {
|
|
74
|
+
const graph = program.command("automation-graph").description("Publish and inspect automation graphs");
|
|
75
|
+
graph.command("get <automation-id>").action(async (id) => printData(await apiJson(`/api/organizations/${requireOrgId()}/automations/${encodeURIComponent(id)}/graph`), true));
|
|
76
|
+
graph.command("trace <automation-id> <run-id>").action(async (id, runId) => printData(await apiJson(`/api/organizations/${requireOrgId()}/automations/${encodeURIComponent(id)}/runs/${encodeURIComponent(runId)}/steps`), true));
|
|
77
|
+
graph.command("configure <automation-id>").requiredOption("--file <path>").action(async (id, options) => {
|
|
78
|
+
const body = await readFile(options.file, "utf8");
|
|
79
|
+
await confirm("Apply these triggers and enabled state?", getContext().yes);
|
|
80
|
+
printData(await apiJson(`/api/organizations/${requireOrgId()}/automations/${encodeURIComponent(id)}/graph`, { method: "PATCH", body }), true);
|
|
81
|
+
});
|
|
82
|
+
graph.command("control <automation-id> <run-id>").requiredOption("--file <path>", "Cancel, retry, or confirmed reconciliation").action(async (id, runId, options) => {
|
|
83
|
+
const body = await readFile(options.file, "utf8");
|
|
84
|
+
await confirm("Apply this run control? Confirm external results before reconciliation.", getContext().yes);
|
|
85
|
+
printData(await apiJson(`/api/organizations/${requireOrgId()}/automations/${encodeURIComponent(id)}/runs/${encodeURIComponent(runId)}/steps`, { method: "POST", body }), true);
|
|
86
|
+
});
|
|
87
|
+
graph.command("publish").requiredOption("--file <path>").action(async (options) => {
|
|
88
|
+
const body = await readFile(options.file, "utf8");
|
|
89
|
+
await confirm("Publish this graph and delegate its listed resource access?", getContext().yes);
|
|
90
|
+
printData(await apiJson(`/api/organizations/${requireOrgId()}/automations/graphs`, { method: "POST", body }), true);
|
|
91
|
+
});
|
|
73
92
|
const automations = program
|
|
74
93
|
.command("automations")
|
|
75
94
|
.description("Standing instructions that run unattended (schedules, webhooks)");
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { apiJson, requireOrgId, getContext } from "../http.js";
|
|
4
|
+
import { confirm, printData } from "../output.js";
|
|
5
|
+
export function tablesCommand() {
|
|
6
|
+
const command = new Command("tables").description("Fieldwork Tables and editable records");
|
|
7
|
+
const base = () => `/api/organizations/${requireOrgId()}/tables`;
|
|
8
|
+
command
|
|
9
|
+
.command("list")
|
|
10
|
+
.action(async () => printData(await apiJson(base()), true));
|
|
11
|
+
command
|
|
12
|
+
.command("create")
|
|
13
|
+
.requiredOption("--file <path>", "Table definition file")
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const body = await readFile(options.file, "utf8");
|
|
16
|
+
await confirm("Create this Fieldwork Table?", getContext().yes);
|
|
17
|
+
printData(await apiJson(base(), { method: "POST", body }), true);
|
|
18
|
+
});
|
|
19
|
+
command
|
|
20
|
+
.command("records <table-id>")
|
|
21
|
+
.option("--after <id>")
|
|
22
|
+
.option("--limit <number>", "Page size", "50")
|
|
23
|
+
.action(async (tableId, options) => {
|
|
24
|
+
const query = new URLSearchParams({ limit: options.limit });
|
|
25
|
+
if (options.after)
|
|
26
|
+
query.set("after", options.after);
|
|
27
|
+
printData(await apiJson(`${base()}/${encodeURIComponent(tableId)}/records?${query}`), true);
|
|
28
|
+
});
|
|
29
|
+
command
|
|
30
|
+
.command("mutate <table-id>")
|
|
31
|
+
.requiredOption("--file <path>", "Record mutation file")
|
|
32
|
+
.action(async (tableId, options) => {
|
|
33
|
+
const body = await readFile(options.file, "utf8");
|
|
34
|
+
await confirm("Apply this record mutation?", getContext().yes);
|
|
35
|
+
printData(await apiJson(`${base()}/${encodeURIComponent(tableId)}/records`, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
body,
|
|
38
|
+
}), true);
|
|
39
|
+
});
|
|
40
|
+
return command;
|
|
41
|
+
}
|
package/dist/http.js
CHANGED
|
@@ -114,7 +114,15 @@ export async function apiJson(pathname, init = {}) {
|
|
|
114
114
|
const res = await api(pathname, init);
|
|
115
115
|
const body = (await res.json().catch(() => null));
|
|
116
116
|
if (!res.ok) {
|
|
117
|
-
|
|
117
|
+
const message = body?.error ?? `request failed (${res.status})`;
|
|
118
|
+
const details = Array.isArray(body?.details) ? body.details.flatMap((issue) => {
|
|
119
|
+
if (!issue || typeof issue !== "object")
|
|
120
|
+
return [];
|
|
121
|
+
const { path, message } = issue;
|
|
122
|
+
return typeof message === "string" ? [`${Array.isArray(path) ? path.join(".") + ": " : ""}${message}`] : [];
|
|
123
|
+
}) : [];
|
|
124
|
+
const prefix = typeof body?.tool === "string" ? `${body.tool}: ` : "";
|
|
125
|
+
fail([prefix + message, ...details].join("\n"), exitCodeFor(res.status));
|
|
118
126
|
}
|
|
119
127
|
return body;
|
|
120
128
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { tablesCommand } from "./commands/tables.js";
|
|
2
3
|
import { Command } from "commander";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
4
5
|
import { initContext } from "./http.js";
|
|
@@ -40,6 +41,7 @@ registerAppCommands(program);
|
|
|
40
41
|
registerAutomationCommands(program);
|
|
41
42
|
registerTaskCommands(program);
|
|
42
43
|
registerConnectorCommands(program);
|
|
44
|
+
program.addCommand(tablesCommand());
|
|
43
45
|
program.parseAsync(process.argv).catch((err) => {
|
|
44
46
|
process.stderr.write(`fieldwork: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
45
47
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fieldwork-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "Fieldwork asset-management CLI",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=24"
|
|
15
15
|
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "node -e \"require('node:fs').rmSync('dist', {recursive:true,force:true})\" && tsc",
|
|
18
|
+
"prepack": "pnpm build",
|
|
19
|
+
"dev": "tsx src/index.ts",
|
|
20
|
+
"test": "vitest run"
|
|
21
|
+
},
|
|
16
22
|
"dependencies": {
|
|
17
23
|
"commander": "^14.0.2"
|
|
18
24
|
},
|
|
@@ -30,10 +36,5 @@
|
|
|
30
36
|
"exports": {
|
|
31
37
|
"./package.json": "./package.json",
|
|
32
38
|
"./*": "./dist/*.js"
|
|
33
|
-
},
|
|
34
|
-
"scripts": {
|
|
35
|
-
"build": "node -e \"require('node:fs').rmSync('dist', {recursive:true,force:true})\" && tsc",
|
|
36
|
-
"dev": "tsx src/index.ts",
|
|
37
|
-
"test": "vitest run"
|
|
38
39
|
}
|
|
39
|
-
}
|
|
40
|
+
}
|