@bctrl/cli 0.1.0 → 0.1.3
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/README.md +78 -27
- package/dist/api/auth.d.ts +1 -0
- package/dist/api/auth.js +1 -0
- package/dist/bin/bctrl.js +0 -0
- package/dist/commands/ai/index.js +25 -17
- package/dist/commands/auth/login.d.ts +3 -0
- package/dist/commands/auth/login.js +19 -5
- package/dist/commands/auth/logout.d.ts +1 -0
- package/dist/commands/auth/logout.js +1 -1
- package/dist/commands/auth/status.d.ts +2 -0
- package/dist/commands/auth/status.js +49 -5
- package/dist/commands/browser/index.js +3 -3
- package/dist/commands/file/index.js +3 -3
- package/dist/commands/invocation/index.js +3 -3
- package/dist/commands/run/index.js +6 -6
- package/dist/commands/runtime/index.js +31 -67
- package/dist/commands/shared/help.d.ts +24 -0
- package/dist/commands/shared/help.js +72 -0
- package/dist/commands/shared/io.js +1 -1
- package/dist/commands/shared/rest.d.ts +1 -1
- package/dist/commands/shared/rest.js +3 -3
- package/dist/commands/space/index.js +6 -6
- package/dist/commands/subaccount/index.js +12 -12
- package/dist/commands/vault/index.js +3 -3
- package/dist/config/auth-store.d.ts +2 -0
- package/dist/config/auth-store.js +1 -0
- package/dist/config/config.js +1 -1
- package/dist/factory.js +1 -1
- package/dist/generated/help.d.ts +134 -0
- package/dist/generated/help.js +179 -0
- package/package.json +10 -12
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { type CliHelpCommandId } from '../../generated/help.js';
|
|
3
|
+
export type CommandHelpField = {
|
|
4
|
+
name: string;
|
|
5
|
+
type: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
description?: string;
|
|
8
|
+
};
|
|
9
|
+
export type CommandHelpFlag = {
|
|
10
|
+
name: string;
|
|
11
|
+
value?: string;
|
|
12
|
+
description: string;
|
|
13
|
+
mapsTo?: string;
|
|
14
|
+
};
|
|
15
|
+
export type CommandHelpSpec = {
|
|
16
|
+
purpose: string;
|
|
17
|
+
flags?: CommandHelpFlag[];
|
|
18
|
+
input?: CommandHelpField[];
|
|
19
|
+
output?: CommandHelpField[];
|
|
20
|
+
examples?: string[];
|
|
21
|
+
next?: string[];
|
|
22
|
+
};
|
|
23
|
+
export declare function addStructuredHelp(command: Command, spec: CommandHelpSpec): Command;
|
|
24
|
+
export declare function addCliHelp(command: Command, commandId: CliHelpCommandId): Command;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { CLI_HELP_COMMANDS } from '../../generated/help.js';
|
|
2
|
+
export function addStructuredHelp(command, spec) {
|
|
3
|
+
command.addHelpText('after', `\n${renderStructuredHelp(spec)}`);
|
|
4
|
+
return command;
|
|
5
|
+
}
|
|
6
|
+
export function addCliHelp(command, commandId) {
|
|
7
|
+
return addStructuredHelp(command, toCommandHelpSpec(CLI_HELP_COMMANDS[commandId]));
|
|
8
|
+
}
|
|
9
|
+
function toCommandHelpSpec(help) {
|
|
10
|
+
const raw = help;
|
|
11
|
+
return {
|
|
12
|
+
purpose: raw.summary,
|
|
13
|
+
flags: raw.flags?.map((flag) => ({ ...flag })),
|
|
14
|
+
input: raw.input?.fields.map((field) => ({ ...field })),
|
|
15
|
+
output: raw.output?.fields.map((field) => ({ ...field })),
|
|
16
|
+
examples: raw.examples?.map(formatHelpItem).filter((value) => Boolean(value)),
|
|
17
|
+
next: raw.next?.map(formatHelpItem).filter((value) => Boolean(value)),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function formatHelpItem(value) {
|
|
21
|
+
if (typeof value === 'string')
|
|
22
|
+
return value;
|
|
23
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
24
|
+
return undefined;
|
|
25
|
+
const record = value;
|
|
26
|
+
if (typeof record.command === 'string')
|
|
27
|
+
return record.command;
|
|
28
|
+
if (typeof record.topic === 'string')
|
|
29
|
+
return record.topic;
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
function renderStructuredHelp(spec) {
|
|
33
|
+
const sections = [
|
|
34
|
+
renderPurpose(spec.purpose),
|
|
35
|
+
spec.flags && spec.flags.length > 0 ? renderFlags(spec.flags) : '',
|
|
36
|
+
spec.input && spec.input.length > 0 ? renderFields('Input', spec.input) : '',
|
|
37
|
+
spec.output && spec.output.length > 0 ? renderFields('Output', spec.output) : '',
|
|
38
|
+
spec.examples && spec.examples.length > 0 ? renderList('Examples', spec.examples) : '',
|
|
39
|
+
spec.next && spec.next.length > 0 ? renderList('Next', spec.next) : '',
|
|
40
|
+
].filter(Boolean);
|
|
41
|
+
return sections.join('\n\n');
|
|
42
|
+
}
|
|
43
|
+
function renderPurpose(purpose) {
|
|
44
|
+
return `Purpose:\n ${purpose}`;
|
|
45
|
+
}
|
|
46
|
+
function renderFlags(flags) {
|
|
47
|
+
const rows = flags.map((flag) => {
|
|
48
|
+
const left = [flag.name, flag.value].filter(Boolean).join(' ');
|
|
49
|
+
const suffix = flag.mapsTo ? ` Maps to ${flag.mapsTo}.` : '';
|
|
50
|
+
return { left, right: `${flag.description}${suffix}` };
|
|
51
|
+
});
|
|
52
|
+
return renderRows('Flags', rows);
|
|
53
|
+
}
|
|
54
|
+
function renderFields(title, fields) {
|
|
55
|
+
const rows = fields.map((field) => ({
|
|
56
|
+
left: field.name,
|
|
57
|
+
right: [
|
|
58
|
+
field.type,
|
|
59
|
+
field.required === true ? 'required' : 'optional',
|
|
60
|
+
field.description,
|
|
61
|
+
].filter(Boolean).join(' '),
|
|
62
|
+
}));
|
|
63
|
+
return renderRows(title, rows);
|
|
64
|
+
}
|
|
65
|
+
function renderRows(title, rows) {
|
|
66
|
+
const width = Math.max(...rows.map((row) => row.left.length));
|
|
67
|
+
const lines = rows.map((row) => ` ${row.left.padEnd(width)} ${row.right}`);
|
|
68
|
+
return `${title}:\n${lines.join('\n')}`;
|
|
69
|
+
}
|
|
70
|
+
function renderList(title, lines) {
|
|
71
|
+
return `${title}:\n${lines.map((line) => ` ${line}`).join('\n')}`;
|
|
72
|
+
}
|
|
@@ -8,7 +8,7 @@ export async function readText(path) {
|
|
|
8
8
|
}
|
|
9
9
|
return readFile(path, 'utf8');
|
|
10
10
|
}
|
|
11
|
-
export async function readJsonFile(path, label = '--
|
|
11
|
+
export async function readJsonFile(path, label = '--input') {
|
|
12
12
|
const text = await readText(path);
|
|
13
13
|
try {
|
|
14
14
|
return JSON.parse(text);
|
|
@@ -16,7 +16,7 @@ export declare function requestAndPrint(deps: ApiDeps, method: ClientMethod, pat
|
|
|
16
16
|
body?: unknown;
|
|
17
17
|
output?: OutputFlags;
|
|
18
18
|
}): Promise<void>;
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function bodyFromInputOption(path: string | undefined): Promise<unknown>;
|
|
20
20
|
export declare function createListCommand(factory: Factory, config: {
|
|
21
21
|
name?: string;
|
|
22
22
|
description: string;
|
|
@@ -12,7 +12,7 @@ export function addPaginationFlags(command) {
|
|
|
12
12
|
.option('--cursor <cursor>', 'Pagination cursor');
|
|
13
13
|
}
|
|
14
14
|
export function addJsonBodyFlag(command) {
|
|
15
|
-
return command.option('--
|
|
15
|
+
return command.option('--input <path>', 'Read JSON request body from file, or - for stdin');
|
|
16
16
|
}
|
|
17
17
|
export async function requestAndPrint(deps, method, path, options) {
|
|
18
18
|
const client = await deps.apiClient();
|
|
@@ -27,7 +27,7 @@ export async function requestAndPrint(deps, method, path, options) {
|
|
|
27
27
|
: await client.delete(path, options);
|
|
28
28
|
await outputData(deps.io, result, options?.output);
|
|
29
29
|
}
|
|
30
|
-
export async function
|
|
30
|
+
export async function bodyFromInputOption(path) {
|
|
31
31
|
return path ? readJsonFile(path) : {};
|
|
32
32
|
}
|
|
33
33
|
export function createListCommand(factory, config) {
|
|
@@ -89,7 +89,7 @@ export function createJsonBodyCommand(factory, config) {
|
|
|
89
89
|
const args = {};
|
|
90
90
|
for (let i = 0; i < argNames.length; i += 1)
|
|
91
91
|
args[argNames[i]] = String(actionArgs[i]);
|
|
92
|
-
const body = config.body ? await config.body(args, options) : await
|
|
92
|
+
const body = config.body ? await config.body(args, options) : await bodyFromInputOption(String(options.input ?? ''));
|
|
93
93
|
await requestAndPrint(factory, config.method, pathTemplate(config.path, args), {
|
|
94
94
|
body,
|
|
95
95
|
query: config.query ? config.query(args, options) : undefined,
|
|
@@ -19,10 +19,10 @@ export function createSpaceCommand(factory) {
|
|
|
19
19
|
.option('--name <name>', 'Space name')
|
|
20
20
|
.option('--region <region>', 'Space region')
|
|
21
21
|
.option('--subaccount-id <id>', 'Subaccount id')
|
|
22
|
-
.option('--
|
|
22
|
+
.option('--input <path>', 'Read JSON request body from file, or - for stdin'),
|
|
23
23
|
body: async (_args, options) => {
|
|
24
|
-
if (typeof options.
|
|
25
|
-
return readJsonFile(options.
|
|
24
|
+
if (typeof options.input === 'string')
|
|
25
|
+
return readJsonFile(options.input);
|
|
26
26
|
return {
|
|
27
27
|
name: options.name,
|
|
28
28
|
region: options.region,
|
|
@@ -38,10 +38,10 @@ export function createSpaceCommand(factory) {
|
|
|
38
38
|
argNames: ['id'],
|
|
39
39
|
configure: (cmd) => cmd
|
|
40
40
|
.option('--name <name>', 'Space name')
|
|
41
|
-
.option('--
|
|
41
|
+
.option('--input <path>', 'Read JSON request body from file, or - for stdin'),
|
|
42
42
|
body: async (_args, options) => {
|
|
43
|
-
if (typeof options.
|
|
44
|
-
return readJsonFile(options.
|
|
43
|
+
if (typeof options.input === 'string')
|
|
44
|
+
return readJsonFile(options.input);
|
|
45
45
|
return { name: options.name };
|
|
46
46
|
},
|
|
47
47
|
}));
|
|
@@ -23,10 +23,10 @@ export function createSubaccountCommand(factory) {
|
|
|
23
23
|
.option('--name <name>', 'Subaccount name')
|
|
24
24
|
.option('--external-id <id>', 'External id')
|
|
25
25
|
.option('--metadata-file <path>', 'Metadata JSON file')
|
|
26
|
-
.option('--
|
|
26
|
+
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
27
27
|
body: async (_args, options) => {
|
|
28
|
-
if (typeof options.
|
|
29
|
-
return readJsonFile(options.
|
|
28
|
+
if (typeof options.input === 'string')
|
|
29
|
+
return readJsonFile(options.input);
|
|
30
30
|
return {
|
|
31
31
|
name: options.name,
|
|
32
32
|
externalId: options.externalId,
|
|
@@ -46,10 +46,10 @@ export function createSubaccountCommand(factory) {
|
|
|
46
46
|
.option('--name <name>', 'Subaccount name')
|
|
47
47
|
.option('--external-id <id>', 'External id')
|
|
48
48
|
.option('--metadata-file <path>', 'Metadata JSON file')
|
|
49
|
-
.option('--
|
|
49
|
+
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
50
50
|
body: async (_args, options) => {
|
|
51
|
-
if (typeof options.
|
|
52
|
-
return readJsonFile(options.
|
|
51
|
+
if (typeof options.input === 'string')
|
|
52
|
+
return readJsonFile(options.input);
|
|
53
53
|
return {
|
|
54
54
|
name: options.name,
|
|
55
55
|
externalId: options.externalId,
|
|
@@ -112,10 +112,10 @@ function createSubaccountLimitsCommand(factory) {
|
|
|
112
112
|
.option('--max-spaces <number>', 'Maximum spaces')
|
|
113
113
|
.option('--max-active-runs <number>', 'Maximum active runs')
|
|
114
114
|
.option('--monthly-spend-micro-usd <number>', 'Monthly spend limit in micro USD')
|
|
115
|
-
.option('--
|
|
115
|
+
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
116
116
|
body: async (_args, options) => {
|
|
117
|
-
if (typeof options.
|
|
118
|
-
return readJsonFile(options.
|
|
117
|
+
if (typeof options.input === 'string')
|
|
118
|
+
return readJsonFile(options.input);
|
|
119
119
|
return {
|
|
120
120
|
spaces: options.maxSpaces ? { max: Number(options.maxSpaces) } : undefined,
|
|
121
121
|
runs: options.maxActiveRuns ? { maxActive: Number(options.maxActiveRuns) } : undefined,
|
|
@@ -145,10 +145,10 @@ function createSubaccountKeyCommand(factory) {
|
|
|
145
145
|
argNames: ['id'],
|
|
146
146
|
configure: (cmd) => cmd
|
|
147
147
|
.option('--name <name>', 'API key name')
|
|
148
|
-
.option('--
|
|
148
|
+
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
149
149
|
body: async (_args, options) => {
|
|
150
|
-
if (typeof options.
|
|
151
|
-
return readJsonFile(options.
|
|
150
|
+
if (typeof options.input === 'string')
|
|
151
|
+
return readJsonFile(options.input);
|
|
152
152
|
return { name: options.name };
|
|
153
153
|
},
|
|
154
154
|
}));
|
|
@@ -63,10 +63,10 @@ function createVaultSetCommand(factory) {
|
|
|
63
63
|
.option('--label <label>', 'Display label')
|
|
64
64
|
.option('--origin <origin...>', 'Allowed origin')
|
|
65
65
|
.option('--origin-pattern <pattern...>', 'Allowed origin pattern')
|
|
66
|
-
.option('--
|
|
66
|
+
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
67
67
|
body: async (args, options) => {
|
|
68
|
-
if (typeof options.
|
|
69
|
-
return readJsonFile(options.
|
|
68
|
+
if (typeof options.input === 'string')
|
|
69
|
+
return readJsonFile(options.input);
|
|
70
70
|
const password = typeof options.passwordFromFile === 'string'
|
|
71
71
|
? (await readText(options.passwordFromFile)).trimEnd()
|
|
72
72
|
: options.password;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const StoredWhoamiSchema: z.ZodObject<{
|
|
3
3
|
authenticated: z.ZodLiteral<true>;
|
|
4
|
+
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
4
5
|
keyKind: z.ZodEnum<{
|
|
5
6
|
user: "user";
|
|
6
7
|
subaccount: "subaccount";
|
|
@@ -17,6 +18,7 @@ export declare const StoredAuthSchema: z.ZodObject<{
|
|
|
17
18
|
token: z.ZodString;
|
|
18
19
|
whoami: z.ZodObject<{
|
|
19
20
|
authenticated: z.ZodLiteral<true>;
|
|
21
|
+
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
20
22
|
keyKind: z.ZodEnum<{
|
|
21
23
|
user: "user";
|
|
22
24
|
subaccount: "subaccount";
|
|
@@ -6,6 +6,7 @@ const DEFAULT_AUTH_FILE_NAME = 'auth.json';
|
|
|
6
6
|
export const StoredWhoamiSchema = z
|
|
7
7
|
.object({
|
|
8
8
|
authenticated: z.literal(true),
|
|
9
|
+
email: z.string().email().nullable().optional(),
|
|
9
10
|
keyKind: z.enum(['user', 'subaccount']),
|
|
10
11
|
organizationId: z.string().min(1),
|
|
11
12
|
subaccountId: z.string().min(1).nullable().optional(),
|
package/dist/config/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { readStoredAuth } from './auth-store.js';
|
|
3
|
-
const DEFAULT_API_BASE_URL = 'https://api.bctrl.ai/
|
|
3
|
+
const DEFAULT_API_BASE_URL = 'https://api.bctrl.ai/v1';
|
|
4
4
|
const EnvSchema = z.object({
|
|
5
5
|
BCTRL_API_KEY: z.string().optional(),
|
|
6
6
|
BCTRL_API_URL: z.string().url().optional(),
|
package/dist/factory.js
CHANGED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
export declare const CLI_HELP_COMMANDS: {
|
|
2
|
+
readonly "runtime.create": {
|
|
3
|
+
readonly kind: "command";
|
|
4
|
+
readonly command: "runtime.create";
|
|
5
|
+
readonly summary: "Create a browser runtime definition. This does not start the browser.";
|
|
6
|
+
readonly usage: "bctrl runtime create [flags]";
|
|
7
|
+
readonly flags: readonly [{
|
|
8
|
+
readonly name: "--space";
|
|
9
|
+
readonly value: "<id>";
|
|
10
|
+
readonly description: "Owning space id.";
|
|
11
|
+
readonly mapsTo: "input.spaceId";
|
|
12
|
+
}, {
|
|
13
|
+
readonly name: "--name";
|
|
14
|
+
readonly value: "<name>";
|
|
15
|
+
readonly description: "Runtime name.";
|
|
16
|
+
readonly mapsTo: "input.name";
|
|
17
|
+
}, {
|
|
18
|
+
readonly name: "--config-file";
|
|
19
|
+
readonly value: "<path>";
|
|
20
|
+
readonly description: "Read runtime config JSON from a file.";
|
|
21
|
+
readonly mapsTo: "input.config";
|
|
22
|
+
}, {
|
|
23
|
+
readonly name: "--metadata-file";
|
|
24
|
+
readonly value: "<path>";
|
|
25
|
+
readonly description: "Read runtime metadata JSON from a file.";
|
|
26
|
+
readonly mapsTo: "input.metadata";
|
|
27
|
+
}, {
|
|
28
|
+
readonly name: "--input";
|
|
29
|
+
readonly value: "<path>";
|
|
30
|
+
readonly description: "Read the full JSON request body from a file, or - for stdin.";
|
|
31
|
+
}];
|
|
32
|
+
readonly input: {
|
|
33
|
+
readonly fields: readonly [{
|
|
34
|
+
readonly name: "spaceId";
|
|
35
|
+
readonly type: "uuid";
|
|
36
|
+
readonly required: true;
|
|
37
|
+
}, {
|
|
38
|
+
readonly name: "type";
|
|
39
|
+
readonly type: "\"browser\"";
|
|
40
|
+
readonly values: readonly ["\"browser\""];
|
|
41
|
+
readonly required: true;
|
|
42
|
+
}, {
|
|
43
|
+
readonly name: "name";
|
|
44
|
+
readonly type: "string";
|
|
45
|
+
readonly required: false;
|
|
46
|
+
}, {
|
|
47
|
+
readonly name: "metadata";
|
|
48
|
+
readonly type: "object";
|
|
49
|
+
readonly required: false;
|
|
50
|
+
}, {
|
|
51
|
+
readonly name: "config";
|
|
52
|
+
readonly type: "object";
|
|
53
|
+
readonly required: false;
|
|
54
|
+
}];
|
|
55
|
+
};
|
|
56
|
+
readonly output: {
|
|
57
|
+
readonly fields: readonly [{
|
|
58
|
+
readonly name: "id";
|
|
59
|
+
readonly type: "uuid";
|
|
60
|
+
readonly required: true;
|
|
61
|
+
}, {
|
|
62
|
+
readonly name: "name";
|
|
63
|
+
readonly type: "string";
|
|
64
|
+
readonly required: true;
|
|
65
|
+
}, {
|
|
66
|
+
readonly name: "type";
|
|
67
|
+
readonly type: "\"browser\" | \"desktop\" | \"spreadsheet\"";
|
|
68
|
+
readonly values: readonly ["\"browser\"", "\"desktop\"", "\"spreadsheet\""];
|
|
69
|
+
readonly required: true;
|
|
70
|
+
}, {
|
|
71
|
+
readonly name: "status";
|
|
72
|
+
readonly type: "\"active\" | \"stopped\" | \"failed\"";
|
|
73
|
+
readonly values: readonly ["\"active\"", "\"stopped\"", "\"failed\""];
|
|
74
|
+
readonly required: true;
|
|
75
|
+
}, {
|
|
76
|
+
readonly name: "activeRunId";
|
|
77
|
+
readonly type: "uuid | null";
|
|
78
|
+
readonly required: true;
|
|
79
|
+
}, {
|
|
80
|
+
readonly name: "createdAt";
|
|
81
|
+
readonly type: "string";
|
|
82
|
+
readonly required: true;
|
|
83
|
+
}, {
|
|
84
|
+
readonly name: "updatedAt";
|
|
85
|
+
readonly type: "string";
|
|
86
|
+
readonly required: true;
|
|
87
|
+
}, {
|
|
88
|
+
readonly name: "config";
|
|
89
|
+
readonly type: "object";
|
|
90
|
+
readonly required: false;
|
|
91
|
+
}, {
|
|
92
|
+
readonly name: "metadata";
|
|
93
|
+
readonly type: "object | null";
|
|
94
|
+
readonly required: false;
|
|
95
|
+
}];
|
|
96
|
+
};
|
|
97
|
+
readonly examples: readonly [{
|
|
98
|
+
readonly command: "bctrl runtime create --space sp_123 --name checkout-test";
|
|
99
|
+
}, {
|
|
100
|
+
readonly command: "bctrl runtime create --input runtime.json";
|
|
101
|
+
}];
|
|
102
|
+
readonly next: readonly [{
|
|
103
|
+
readonly command: "bctrl runtime start <runtimeId>";
|
|
104
|
+
}];
|
|
105
|
+
};
|
|
106
|
+
readonly "runtime.start": {
|
|
107
|
+
readonly kind: "command";
|
|
108
|
+
readonly command: "runtime.start";
|
|
109
|
+
readonly summary: "Start a runtime and open its active run.";
|
|
110
|
+
readonly usage: "bctrl runtime start <runtimeId>";
|
|
111
|
+
readonly output: {
|
|
112
|
+
readonly fields: readonly [{
|
|
113
|
+
readonly name: "runtime";
|
|
114
|
+
readonly type: "object";
|
|
115
|
+
readonly required: true;
|
|
116
|
+
}, {
|
|
117
|
+
readonly name: "run";
|
|
118
|
+
readonly type: "object";
|
|
119
|
+
readonly required: true;
|
|
120
|
+
}, {
|
|
121
|
+
readonly name: "browser";
|
|
122
|
+
readonly type: "object";
|
|
123
|
+
readonly required: true;
|
|
124
|
+
}];
|
|
125
|
+
};
|
|
126
|
+
readonly examples: readonly [{
|
|
127
|
+
readonly command: "bctrl runtime start rt_123";
|
|
128
|
+
}];
|
|
129
|
+
readonly next: readonly [{
|
|
130
|
+
readonly command: "bctrl run events <runId>";
|
|
131
|
+
}];
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
export type CliHelpCommandId = keyof typeof CLI_HELP_COMMANDS;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// Generated by scripts/generate/cli-help.mjs. Do not edit by hand.
|
|
2
|
+
export const CLI_HELP_COMMANDS = {
|
|
3
|
+
"runtime.create": {
|
|
4
|
+
"kind": "command",
|
|
5
|
+
"command": "runtime.create",
|
|
6
|
+
"summary": "Create a browser runtime definition. This does not start the browser.",
|
|
7
|
+
"usage": "bctrl runtime create [flags]",
|
|
8
|
+
"flags": [
|
|
9
|
+
{
|
|
10
|
+
"name": "--space",
|
|
11
|
+
"value": "<id>",
|
|
12
|
+
"description": "Owning space id.",
|
|
13
|
+
"mapsTo": "input.spaceId"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "--name",
|
|
17
|
+
"value": "<name>",
|
|
18
|
+
"description": "Runtime name.",
|
|
19
|
+
"mapsTo": "input.name"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "--config-file",
|
|
23
|
+
"value": "<path>",
|
|
24
|
+
"description": "Read runtime config JSON from a file.",
|
|
25
|
+
"mapsTo": "input.config"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "--metadata-file",
|
|
29
|
+
"value": "<path>",
|
|
30
|
+
"description": "Read runtime metadata JSON from a file.",
|
|
31
|
+
"mapsTo": "input.metadata"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "--input",
|
|
35
|
+
"value": "<path>",
|
|
36
|
+
"description": "Read the full JSON request body from a file, or - for stdin."
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"input": {
|
|
40
|
+
"fields": [
|
|
41
|
+
{
|
|
42
|
+
"name": "spaceId",
|
|
43
|
+
"type": "uuid",
|
|
44
|
+
"required": true
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "type",
|
|
48
|
+
"type": "\"browser\"",
|
|
49
|
+
"values": [
|
|
50
|
+
"\"browser\""
|
|
51
|
+
],
|
|
52
|
+
"required": true
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "name",
|
|
56
|
+
"type": "string",
|
|
57
|
+
"required": false
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "metadata",
|
|
61
|
+
"type": "object",
|
|
62
|
+
"required": false
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "config",
|
|
66
|
+
"type": "object",
|
|
67
|
+
"required": false
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"output": {
|
|
72
|
+
"fields": [
|
|
73
|
+
{
|
|
74
|
+
"name": "id",
|
|
75
|
+
"type": "uuid",
|
|
76
|
+
"required": true
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "name",
|
|
80
|
+
"type": "string",
|
|
81
|
+
"required": true
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "type",
|
|
85
|
+
"type": "\"browser\" | \"desktop\" | \"spreadsheet\"",
|
|
86
|
+
"values": [
|
|
87
|
+
"\"browser\"",
|
|
88
|
+
"\"desktop\"",
|
|
89
|
+
"\"spreadsheet\""
|
|
90
|
+
],
|
|
91
|
+
"required": true
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "status",
|
|
95
|
+
"type": "\"active\" | \"stopped\" | \"failed\"",
|
|
96
|
+
"values": [
|
|
97
|
+
"\"active\"",
|
|
98
|
+
"\"stopped\"",
|
|
99
|
+
"\"failed\""
|
|
100
|
+
],
|
|
101
|
+
"required": true
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "activeRunId",
|
|
105
|
+
"type": "uuid | null",
|
|
106
|
+
"required": true
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "createdAt",
|
|
110
|
+
"type": "string",
|
|
111
|
+
"required": true
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "updatedAt",
|
|
115
|
+
"type": "string",
|
|
116
|
+
"required": true
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"name": "config",
|
|
120
|
+
"type": "object",
|
|
121
|
+
"required": false
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "metadata",
|
|
125
|
+
"type": "object | null",
|
|
126
|
+
"required": false
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
"examples": [
|
|
131
|
+
{
|
|
132
|
+
"command": "bctrl runtime create --space sp_123 --name checkout-test"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"command": "bctrl runtime create --input runtime.json"
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"next": [
|
|
139
|
+
{
|
|
140
|
+
"command": "bctrl runtime start <runtimeId>"
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
"runtime.start": {
|
|
145
|
+
"kind": "command",
|
|
146
|
+
"command": "runtime.start",
|
|
147
|
+
"summary": "Start a runtime and open its active run.",
|
|
148
|
+
"usage": "bctrl runtime start <runtimeId>",
|
|
149
|
+
"output": {
|
|
150
|
+
"fields": [
|
|
151
|
+
{
|
|
152
|
+
"name": "runtime",
|
|
153
|
+
"type": "object",
|
|
154
|
+
"required": true
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"name": "run",
|
|
158
|
+
"type": "object",
|
|
159
|
+
"required": true
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"name": "browser",
|
|
163
|
+
"type": "object",
|
|
164
|
+
"required": true
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
"examples": [
|
|
169
|
+
{
|
|
170
|
+
"command": "bctrl runtime start rt_123"
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
"next": [
|
|
174
|
+
{
|
|
175
|
+
"command": "bctrl run events <runId>"
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bctrl/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "BCTRL command-line interface",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,15 +15,6 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
|
-
"scripts": {
|
|
19
|
-
"clean": "rm -rf dist",
|
|
20
|
-
"build": "pnpm run clean && tsc -p tsconfig.json",
|
|
21
|
-
"dev": "tsx src/bin/bctrl.ts",
|
|
22
|
-
"prepack": "pnpm run build",
|
|
23
|
-
"test": "tsx --test \"tests/**/*.test.ts\"",
|
|
24
|
-
"typecheck": "tsc --noEmit",
|
|
25
|
-
"typecheck:tests": "tsc --noEmit -p tests/tsconfig.json"
|
|
26
|
-
},
|
|
27
18
|
"keywords": [
|
|
28
19
|
"bctrl",
|
|
29
20
|
"cli",
|
|
@@ -32,7 +23,6 @@
|
|
|
32
23
|
],
|
|
33
24
|
"author": "",
|
|
34
25
|
"license": "ISC",
|
|
35
|
-
"packageManager": "pnpm@10.12.4",
|
|
36
26
|
"dependencies": {
|
|
37
27
|
"commander": "^14.0.3",
|
|
38
28
|
"handlebars": "^4.7.9",
|
|
@@ -43,5 +33,13 @@
|
|
|
43
33
|
"@types/node": "^25.7.0",
|
|
44
34
|
"tsx": "^4.21.0",
|
|
45
35
|
"typescript": "^6.0.3"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"clean": "rm -rf dist",
|
|
39
|
+
"build": "pnpm run clean && tsc -p tsconfig.json",
|
|
40
|
+
"dev": "tsx src/bin/bctrl.ts",
|
|
41
|
+
"test": "tsx --test \"tests/**/*.test.ts\"",
|
|
42
|
+
"typecheck": "tsc --noEmit",
|
|
43
|
+
"typecheck:tests": "tsc --noEmit -p tests/tsconfig.json"
|
|
46
44
|
}
|
|
47
|
-
}
|
|
45
|
+
}
|