@imbrace/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/run.js +5 -0
- package/dist/base-command.d.ts +8 -0
- package/dist/base-command.js +48 -0
- package/dist/commands/ai-agent/create.d.ts +28 -0
- package/dist/commands/ai-agent/create.js +86 -0
- package/dist/commands/ai-agent/delete.d.ts +13 -0
- package/dist/commands/ai-agent/delete.js +39 -0
- package/dist/commands/ai-agent/get.d.ts +12 -0
- package/dist/commands/ai-agent/get.js +42 -0
- package/dist/commands/ai-agent/list-models.d.ts +10 -0
- package/dist/commands/ai-agent/list-models.js +36 -0
- package/dist/commands/ai-agent/list-providers.d.ts +9 -0
- package/dist/commands/ai-agent/list-providers.js +37 -0
- package/dist/commands/ai-agent/list.d.ts +9 -0
- package/dist/commands/ai-agent/list.js +36 -0
- package/dist/commands/ai-agent/update.d.ts +30 -0
- package/dist/commands/ai-agent/update.js +100 -0
- package/dist/commands/data-board/create-field.d.ts +14 -0
- package/dist/commands/data-board/create-field.js +46 -0
- package/dist/commands/data-board/create-item.d.ts +13 -0
- package/dist/commands/data-board/create-item.js +72 -0
- package/dist/commands/data-board/create.d.ts +10 -0
- package/dist/commands/data-board/create.js +45 -0
- package/dist/commands/data-board/delete-item.d.ts +14 -0
- package/dist/commands/data-board/delete-item.js +42 -0
- package/dist/commands/data-board/export-csv.d.ts +10 -0
- package/dist/commands/data-board/export-csv.js +34 -0
- package/dist/commands/data-board/list-items.d.ts +13 -0
- package/dist/commands/data-board/list-items.js +47 -0
- package/dist/commands/data-board/list.d.ts +9 -0
- package/dist/commands/data-board/list.js +33 -0
- package/dist/commands/data-board/update-item.d.ts +14 -0
- package/dist/commands/data-board/update-item.js +57 -0
- package/dist/commands/login.d.ts +12 -0
- package/dist/commands/login.js +71 -0
- package/dist/commands/logout.d.ts +6 -0
- package/dist/commands/logout.js +10 -0
- package/dist/commands/whoami.d.ts +9 -0
- package/dist/commands/whoami.js +29 -0
- package/dist/commands/workflow/create.d.ts +12 -0
- package/dist/commands/workflow/create.js +45 -0
- package/dist/commands/workflow/delete.d.ts +13 -0
- package/dist/commands/workflow/delete.js +40 -0
- package/dist/commands/workflow/get.d.ts +12 -0
- package/dist/commands/workflow/get.js +54 -0
- package/dist/commands/workflow/list.d.ts +9 -0
- package/dist/commands/workflow/list.js +36 -0
- package/dist/commands/workflow/node/add.d.ts +20 -0
- package/dist/commands/workflow/node/add.js +72 -0
- package/dist/commands/workflow/node/delete.d.ts +14 -0
- package/dist/commands/workflow/node/delete.js +40 -0
- package/dist/commands/workflow/node/list.d.ts +12 -0
- package/dist/commands/workflow/node/list.js +40 -0
- package/dist/commands/workflow/node/update.d.ts +15 -0
- package/dist/commands/workflow/node/update.js +47 -0
- package/dist/commands/workflow/piece/detail.d.ts +13 -0
- package/dist/commands/workflow/piece/detail.js +60 -0
- package/dist/commands/workflow/piece/list.d.ts +10 -0
- package/dist/commands/workflow/piece/list.js +40 -0
- package/dist/commands/workflow/run-detail.d.ts +12 -0
- package/dist/commands/workflow/run-detail.js +50 -0
- package/dist/commands/workflow/runs.d.ts +10 -0
- package/dist/commands/workflow/runs.js +40 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.js +36 -0
- package/dist/http.d.ts +9 -0
- package/dist/http.js +40 -0
- package/dist/select-board.d.ts +1 -0
- package/dist/select-board.js +12 -0
- package/package.json +71 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class DataBoardCreateItem extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
boardId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { input } from "@inquirer/prompts";
|
|
4
|
+
import { apiRequest } from "../../http.js";
|
|
5
|
+
export default class DataBoardCreateItem extends BaseCommand {
|
|
6
|
+
static description = "Create board items (records). Format: { fields: [{ board_field_id, value }, ...] }";
|
|
7
|
+
static examples = [
|
|
8
|
+
"imbrace data-board create-item",
|
|
9
|
+
`imbrace data-board create-item <boardId> --fields '[{"board_field_id":"<id>","value":"Acme"}]' --json`,
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
boardId: Args.string({ description: "Board ID" }),
|
|
13
|
+
};
|
|
14
|
+
static flags = {
|
|
15
|
+
fields: Flags.string({
|
|
16
|
+
char: "f",
|
|
17
|
+
description: 'JSON: [{"board_field_id":"<id>","value":"<val>"}]',
|
|
18
|
+
}),
|
|
19
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { args, flags } = await this.parse(DataBoardCreateItem);
|
|
23
|
+
const boardId = args.boardId ?? (await input({ message: "Board ID:" }));
|
|
24
|
+
let fields;
|
|
25
|
+
if (flags.fields) {
|
|
26
|
+
try {
|
|
27
|
+
fields = JSON.parse(flags.fields);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
this.error("--fields must be valid JSON array");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const boardRes = await apiRequest(`/data-board/${boardId}/fields`);
|
|
35
|
+
const boardFields = boardRes.data || [];
|
|
36
|
+
if (!boardFields.length)
|
|
37
|
+
this.error("Board has no fields. Run: imbrace data-board create-field");
|
|
38
|
+
this.log("\n Fill in the fields:\n");
|
|
39
|
+
fields = [];
|
|
40
|
+
for (const field of boardFields) {
|
|
41
|
+
const value = await input({
|
|
42
|
+
message: ` ${field.name} (${field.type}):`,
|
|
43
|
+
default: "",
|
|
44
|
+
});
|
|
45
|
+
if (value)
|
|
46
|
+
fields.push({ board_field_id: field._id, value });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const res = await apiRequest(`/data-board/${boardId}/items`, { method: "POST", body: { fields } });
|
|
51
|
+
if (flags.json) {
|
|
52
|
+
this.log(JSON.stringify(res, null, 2));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.log(`\n✅ ${res.message}`);
|
|
56
|
+
if (res.data?._id)
|
|
57
|
+
this.log(` ID: ${res.data._id}`);
|
|
58
|
+
this.log("");
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
this.error(`Failed: ${error.message}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Create board items (records)
|
|
66
|
+
// Items use { fields: [{ board_field_id, value }] } format:
|
|
67
|
+
// const item = await client.boards.createItem(board._id, {
|
|
68
|
+
// fields: [
|
|
69
|
+
// { board_field_id: identifierField._id, value: "Acme Corp", board_field_id: identifierField._id, value: "Acme Corp" },
|
|
70
|
+
// ], { board_field_id: identifierField._id, value: "Acme Corp" },
|
|
71
|
+
// })
|
|
72
|
+
// console.log("Item ID:", item._id)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class DataBoardCreate extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { input, confirm } from "@inquirer/prompts";
|
|
4
|
+
import { apiRequest } from "../../http.js";
|
|
5
|
+
export default class DataBoardCreate extends BaseCommand {
|
|
6
|
+
static description = "Create a new data board";
|
|
7
|
+
static examples = [
|
|
8
|
+
"imbrace data-board create",
|
|
9
|
+
'imbrace data-board create --name "Sales Pipeline" --json',
|
|
10
|
+
];
|
|
11
|
+
static flags = {
|
|
12
|
+
name: Flags.string({ char: "n", description: "Board name" }),
|
|
13
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
14
|
+
};
|
|
15
|
+
async run() {
|
|
16
|
+
const { flags } = await this.parse(DataBoardCreate);
|
|
17
|
+
const name = flags.name ?? await input({ message: "Board name:" });
|
|
18
|
+
const body = { name };
|
|
19
|
+
if (!flags.json) {
|
|
20
|
+
this.log("\n ℹ Board body is freestyle — you can add any field (e.g. description, email, type, owner...)\n");
|
|
21
|
+
while (true) {
|
|
22
|
+
const addMore = await confirm({ message: "Add another field?", default: true });
|
|
23
|
+
if (!addMore)
|
|
24
|
+
break;
|
|
25
|
+
const fieldName = await input({ message: "Field name:" });
|
|
26
|
+
const fieldValue = await input({ message: "Field value:" });
|
|
27
|
+
body[fieldName] = fieldValue;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const res = await apiRequest("/data-board/create", { method: "POST", body });
|
|
32
|
+
if (flags.json) {
|
|
33
|
+
this.log(JSON.stringify(res, null, 2));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.log(`\n✅ ${res.message}`);
|
|
37
|
+
if (res.data?._id)
|
|
38
|
+
this.log(` ID: ${res.data._id}`);
|
|
39
|
+
this.log("");
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
this.error(`Failed: ${error.message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class DataBoardDeleteItem extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
boardId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
itemId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { input, confirm } from "@inquirer/prompts";
|
|
4
|
+
import { apiRequest } from "../../http.js";
|
|
5
|
+
export default class DataBoardDeleteItem extends BaseCommand {
|
|
6
|
+
static description = "Delete an item from a board";
|
|
7
|
+
static examples = [
|
|
8
|
+
"imbrace data-board delete-item",
|
|
9
|
+
"imbrace data-board delete-item <boardId> <itemId> --yes --json",
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
boardId: Args.string({ description: "Board ID" }),
|
|
13
|
+
itemId: Args.string({ description: "Item ID" }),
|
|
14
|
+
};
|
|
15
|
+
static flags = {
|
|
16
|
+
yes: Flags.boolean({ char: "y", description: "Skip confirmation" }),
|
|
17
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
18
|
+
};
|
|
19
|
+
async run() {
|
|
20
|
+
const { args, flags } = await this.parse(DataBoardDeleteItem);
|
|
21
|
+
const boardId = args.boardId ?? await input({ message: "Board ID:" });
|
|
22
|
+
const itemId = args.itemId ?? await input({ message: "Item ID:" });
|
|
23
|
+
if (!flags.yes) {
|
|
24
|
+
const ok = await confirm({ message: `Delete item ${itemId}?`, default: false });
|
|
25
|
+
if (!ok) {
|
|
26
|
+
this.log("Cancelled.");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const res = await apiRequest(`/data-board/${boardId}/items/${itemId}`, { method: "DELETE" });
|
|
32
|
+
if (flags.json) {
|
|
33
|
+
this.log(JSON.stringify(res, null, 2));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.log(`\n✅ ${res.message}\n`);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
this.error(`Failed: ${error.message}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class DataBoardExportCsv extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
"board-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
out: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { input } from "@inquirer/prompts";
|
|
4
|
+
import { writeFileSync } from "fs";
|
|
5
|
+
import { apiRequestText } from "../../http.js";
|
|
6
|
+
export default class DataBoardExportCsv extends BaseCommand {
|
|
7
|
+
static description = "Export a board to CSV";
|
|
8
|
+
static examples = [
|
|
9
|
+
"imbrace data-board export-csv",
|
|
10
|
+
"imbrace data-board export-csv --board-id <id> --out ./board.csv",
|
|
11
|
+
];
|
|
12
|
+
static flags = {
|
|
13
|
+
"board-id": Flags.string({ description: "Board ID" }),
|
|
14
|
+
out: Flags.string({ char: "o", description: "Save to file path (default: print to stdout)" }),
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
const { flags } = await this.parse(DataBoardExportCsv);
|
|
18
|
+
const boardId = flags["board-id"] ?? await input({ message: "Board ID:" });
|
|
19
|
+
const out = flags.out ?? await input({ message: "Save to file path (leave empty to print):", default: "" });
|
|
20
|
+
try {
|
|
21
|
+
const csv = await apiRequestText(`/data-board/${boardId}/export-csv`);
|
|
22
|
+
if (out) {
|
|
23
|
+
writeFileSync(out, csv);
|
|
24
|
+
this.log(`\n✅ Exported to ${out}\n`);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
this.log(csv);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
this.error(`Failed: ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class DataBoardListItems extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
"board-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
q: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
limit: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
skip: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { input } from "@inquirer/prompts";
|
|
4
|
+
import { apiRequest } from "../../http.js";
|
|
5
|
+
export default class DataBoardListItems extends BaseCommand {
|
|
6
|
+
static description = "List or search items (records) in a board";
|
|
7
|
+
static examples = [
|
|
8
|
+
"imbrace data-board list-items",
|
|
9
|
+
"imbrace data-board list-items --board-id <id> --limit 20 --skip 0 --json",
|
|
10
|
+
"imbrace data-board list-items --board-id <id> --q Acme --json",
|
|
11
|
+
];
|
|
12
|
+
static flags = {
|
|
13
|
+
"board-id": Flags.string({ description: "Board ID (brd_...)" }),
|
|
14
|
+
q: Flags.string({ description: "Search query (optional)" }),
|
|
15
|
+
limit: Flags.integer({ char: "l", description: "Number of items (default: 20)" }),
|
|
16
|
+
skip: Flags.integer({ char: "s", description: "Items to skip (default: 0)" }),
|
|
17
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
18
|
+
};
|
|
19
|
+
async run() {
|
|
20
|
+
const { flags } = await this.parse(DataBoardListItems);
|
|
21
|
+
const boardId = flags["board-id"] ?? (flags.json ? this.error("--board-id is required with --json") : await input({ message: "Board ID (brd_...):" }));
|
|
22
|
+
const q = flags.q ?? (flags.json ? "" : await input({ message: "Search query (press Enter to list all):", default: "" }));
|
|
23
|
+
const limit = flags.limit ?? (flags.json ? 20 : Number(await input({ message: "Limit (press Enter for 20):", default: "20" })));
|
|
24
|
+
const skip = flags.skip ?? (flags.json || q ? 0 : Number(await input({ message: "Skip (press Enter for 0):", default: "0" })));
|
|
25
|
+
const params = new URLSearchParams();
|
|
26
|
+
if (q)
|
|
27
|
+
params.set("q", q);
|
|
28
|
+
params.set("limit", String(limit));
|
|
29
|
+
if (!q)
|
|
30
|
+
params.set("skip", String(skip));
|
|
31
|
+
try {
|
|
32
|
+
const res = await apiRequest(`/data-board/${boardId}/items?${params}`);
|
|
33
|
+
if (flags.json) {
|
|
34
|
+
this.log(JSON.stringify(res, null, 2));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
this.log(`\n Found ${res.count} item(s):\n`);
|
|
38
|
+
for (const item of res.data || []) {
|
|
39
|
+
this.log(` ${item._id}`);
|
|
40
|
+
}
|
|
41
|
+
this.log("");
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
this.error(`Failed: ${error.message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class DataBoardList extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { apiRequest } from "../../http.js";
|
|
4
|
+
export default class DataBoardList extends BaseCommand {
|
|
5
|
+
static description = "List all boards — use this to get Board IDs";
|
|
6
|
+
static examples = [
|
|
7
|
+
"imbrace data-board list",
|
|
8
|
+
"imbrace data-board list --json",
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
const { flags } = await this.parse(DataBoardList);
|
|
15
|
+
try {
|
|
16
|
+
const res = await apiRequest("/data-board/list");
|
|
17
|
+
if (flags.json) {
|
|
18
|
+
this.log(JSON.stringify(res, null, 2));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
this.log(`\n Found ${res.count} board(s):\n`);
|
|
22
|
+
this.log(" ID NAME");
|
|
23
|
+
this.log(" ──────────────────────────────────────────────────────");
|
|
24
|
+
for (const board of res.data || []) {
|
|
25
|
+
this.log(` ${(board._id || "").padEnd(38)} ${board.name || ""}`);
|
|
26
|
+
}
|
|
27
|
+
this.log("");
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
this.error(`Failed: ${error.message}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class DataBoardUpdateItem extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
boardId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
itemId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
data: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { input } from "@inquirer/prompts";
|
|
4
|
+
import { apiRequest } from "../../http.js";
|
|
5
|
+
export default class DataBoardUpdateItem extends BaseCommand {
|
|
6
|
+
static description = "Update an item in a board. Fetches fields and prompts per field.";
|
|
7
|
+
static examples = [
|
|
8
|
+
"imbrace data-board update-item",
|
|
9
|
+
`imbrace data-board update-item <boardId> <itemId> --data '[{"key":"<fieldId>","value":"New"}]' --json`,
|
|
10
|
+
];
|
|
11
|
+
static args = {
|
|
12
|
+
boardId: Args.string({ description: "Board ID" }),
|
|
13
|
+
itemId: Args.string({ description: "Item ID" }),
|
|
14
|
+
};
|
|
15
|
+
static flags = {
|
|
16
|
+
data: Flags.string({ char: "d", description: 'JSON: [{"key":"<fieldId>","value":"<val>"}]' }),
|
|
17
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
18
|
+
};
|
|
19
|
+
async run() {
|
|
20
|
+
const { args, flags } = await this.parse(DataBoardUpdateItem);
|
|
21
|
+
const boardId = args.boardId ?? await input({ message: "Board ID:" });
|
|
22
|
+
const itemId = args.itemId ?? await input({ message: "Item ID:" });
|
|
23
|
+
let data;
|
|
24
|
+
if (flags.data) {
|
|
25
|
+
try {
|
|
26
|
+
data = JSON.parse(flags.data);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
this.error("--data must be valid JSON array");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const boardRes = await apiRequest(`/data-board/${boardId}/fields`);
|
|
34
|
+
const boardFields = boardRes.data || [];
|
|
35
|
+
if (!boardFields.length)
|
|
36
|
+
this.error("Board has no fields.");
|
|
37
|
+
this.log("\n Update fields (leave empty to skip):\n");
|
|
38
|
+
data = [];
|
|
39
|
+
for (const field of boardFields) {
|
|
40
|
+
const value = await input({ message: ` ${field.name} (${field.type}):`, default: "" });
|
|
41
|
+
if (value)
|
|
42
|
+
data.push({ key: field._id, value });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const res = await apiRequest(`/data-board/${boardId}/items/${itemId}`, { method: "PUT", body: { data } });
|
|
47
|
+
if (flags.json) {
|
|
48
|
+
this.log(JSON.stringify(res, null, 2));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.log(`\n✅ ${res.message}\n`);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
this.error(`Failed: ${error.message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
export default class Login extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
email: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
password: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
"api-key": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
"api-url": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Command, Flags } from "@oclif/core";
|
|
2
|
+
import { saveCredential, config } from "../config.js";
|
|
3
|
+
import { apiRequest } from "../http.js";
|
|
4
|
+
export default class Login extends Command {
|
|
5
|
+
static description = "Login to Imbrace platform";
|
|
6
|
+
static examples = [
|
|
7
|
+
"imbrace login --email user@example.com --password mypass",
|
|
8
|
+
"imbrace login --api-key sk-xxx...",
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
email: Flags.string({
|
|
12
|
+
char: "e",
|
|
13
|
+
description: "Email address",
|
|
14
|
+
}),
|
|
15
|
+
password: Flags.string({
|
|
16
|
+
char: "p",
|
|
17
|
+
description: "Password",
|
|
18
|
+
}),
|
|
19
|
+
"api-key": Flags.string({
|
|
20
|
+
char: "k",
|
|
21
|
+
description: "API key (starts with sk-)",
|
|
22
|
+
}),
|
|
23
|
+
"api-url": Flags.string({
|
|
24
|
+
description: "Custom API URL",
|
|
25
|
+
default: "http://localhost:3456",
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async run() {
|
|
29
|
+
const { flags } = await this.parse(Login);
|
|
30
|
+
// Set API URL
|
|
31
|
+
if (flags["api-url"]) {
|
|
32
|
+
config.set("apiUrl", flags["api-url"]);
|
|
33
|
+
}
|
|
34
|
+
let body;
|
|
35
|
+
if (flags["api-key"]) {
|
|
36
|
+
// Method 1: API Key
|
|
37
|
+
body = { apiKey: flags["api-key"] };
|
|
38
|
+
this.log("🔑 Logging in with API key...");
|
|
39
|
+
}
|
|
40
|
+
else if (flags.email && flags.password) {
|
|
41
|
+
// Method 2: Email + Password
|
|
42
|
+
body = { email: flags.email, password: flags.password };
|
|
43
|
+
this.log(`📧 Logging in as ${flags.email}...`);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.error("Provide --email + --password, or --api-key\n" +
|
|
47
|
+
" imbrace login --api-key sk-xxx...\n" +
|
|
48
|
+
" imbrace login --email user@example.com --password mypass");
|
|
49
|
+
}
|
|
50
|
+
console.log("[login] POST /auth/login →", JSON.stringify(body));
|
|
51
|
+
try {
|
|
52
|
+
const res = await apiRequest("/auth/login", { method: "POST", body });
|
|
53
|
+
console.log("[login] response →", JSON.stringify(res));
|
|
54
|
+
saveCredential({
|
|
55
|
+
credential: res.credential,
|
|
56
|
+
method: res.method,
|
|
57
|
+
email: res.email,
|
|
58
|
+
});
|
|
59
|
+
this.log(`\n✅ ${res.message}`);
|
|
60
|
+
this.log(` Method: ${res.method}`);
|
|
61
|
+
// this.log(` API URL: ${config.get("apiUrl")}`);
|
|
62
|
+
// this.log(` Config: ${config.path}\n`);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.log("[login] error →", error);
|
|
66
|
+
this.error(`Login failed: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// imbrace login --api-key api_108f337f-a4a8-445e-8e24-9c6bf96fb72b
|
|
71
|
+
// imbrace login --email user@example.com --password mypass
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
import { clearCredential } from "../config.js";
|
|
3
|
+
export default class Logout extends Command {
|
|
4
|
+
static description = "Logout and clear saved credentials";
|
|
5
|
+
static examples = ["imbrace logout"];
|
|
6
|
+
async run() {
|
|
7
|
+
clearCredential();
|
|
8
|
+
this.log("✅ Logged out. Credentials cleared.");
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Command, Flags } from "@oclif/core";
|
|
2
|
+
import { getAuthInfo } from "../config.js";
|
|
3
|
+
export default class Whoami extends Command {
|
|
4
|
+
static description = "Show current login info";
|
|
5
|
+
static examples = ["imbrace whoami", "imbrace whoami --json"];
|
|
6
|
+
static flags = {
|
|
7
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
8
|
+
};
|
|
9
|
+
async run() {
|
|
10
|
+
const { flags } = await this.parse(Whoami);
|
|
11
|
+
const info = getAuthInfo();
|
|
12
|
+
if (!info.credential) {
|
|
13
|
+
this.error("Not logged in. Run: imbrace login --help");
|
|
14
|
+
}
|
|
15
|
+
if (flags.json) {
|
|
16
|
+
this.log(JSON.stringify({
|
|
17
|
+
email: info.email || null,
|
|
18
|
+
method: info.method,
|
|
19
|
+
apiUrl: info.apiUrl,
|
|
20
|
+
authenticated: true,
|
|
21
|
+
}, null, 2));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
this.log(`\n Email: ${info.email || "(api-key)"}`);
|
|
25
|
+
this.log(` Method: ${info.method}`);
|
|
26
|
+
this.log(` API URL: ${info.apiUrl}`);
|
|
27
|
+
this.log(` Status: authenticated\n`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class WorkflowCreate extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
"project-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
"id-only": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { input } from "@inquirer/prompts";
|
|
4
|
+
import { apiRequest } from "../../http.js";
|
|
5
|
+
export default class WorkflowCreate extends BaseCommand {
|
|
6
|
+
static description = "Create a new workflow (empty — add nodes via UI builder or `workflow node add`)";
|
|
7
|
+
static examples = [
|
|
8
|
+
'imbrace workflow create --name "My Flow" --json',
|
|
9
|
+
'imbrace workflow create --name "Slack Bot" --id-only',
|
|
10
|
+
];
|
|
11
|
+
static flags = {
|
|
12
|
+
name: Flags.string({ char: "n", description: "Workflow display name (required)" }),
|
|
13
|
+
"project-id": Flags.string({ description: "Project ID. Auto-discovered from existing flows if omitted." }),
|
|
14
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
15
|
+
"id-only": Flags.boolean({ description: "Print only the new workflow ID (pipe-friendly)" }),
|
|
16
|
+
};
|
|
17
|
+
async run() {
|
|
18
|
+
const { flags } = await this.parse(WorkflowCreate);
|
|
19
|
+
const nonInteractive = flags.json || flags["id-only"];
|
|
20
|
+
const name = flags.name ?? (nonInteractive ? this.error("--name is required with --json or --id-only") : await input({ message: "Workflow name:" }));
|
|
21
|
+
const body = { name };
|
|
22
|
+
if (flags["project-id"])
|
|
23
|
+
body.projectId = flags["project-id"];
|
|
24
|
+
try {
|
|
25
|
+
const res = await apiRequest("/workflow/create", { method: "POST", body });
|
|
26
|
+
if (flags["id-only"]) {
|
|
27
|
+
this.log(res.data?.id ?? "");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (flags.json) {
|
|
31
|
+
this.log(JSON.stringify(res, null, 2));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.log(`\n✅ ${res.message}`);
|
|
35
|
+
if (res.data?.id)
|
|
36
|
+
this.log(` ID: ${res.data.id}`);
|
|
37
|
+
if (res.data?.projectId)
|
|
38
|
+
this.log(` Project: ${res.data.projectId}`);
|
|
39
|
+
this.log("");
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
this.error(`Failed: ${error.message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class WorkflowDelete extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|