@bctrl/cli 0.1.3 → 0.1.5
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 +95 -95
- package/dist/api/auth.d.ts +5 -6
- package/dist/api/auth.js +4 -5
- package/dist/api/client.d.ts +1 -0
- package/dist/api/client.js +3 -0
- package/dist/api/errors.js +2 -2
- package/dist/bin/bctrl.js +0 -0
- package/dist/commands/ai/index.js +71 -106
- package/dist/commands/{browser → api-key}/index.d.ts +1 -1
- package/dist/commands/api-key/index.js +47 -0
- package/dist/commands/auth/login.js +2 -1
- package/dist/commands/auth/status.js +5 -0
- package/dist/commands/browser-extension/index.d.ts +3 -0
- package/dist/commands/browser-extension/index.js +85 -0
- package/dist/commands/file/index.js +26 -21
- package/dist/commands/{invocation → help}/index.d.ts +1 -1
- package/dist/commands/help/index.js +17 -0
- package/dist/commands/proxy/index.d.ts +3 -0
- package/dist/commands/proxy/index.js +72 -0
- package/dist/commands/run/index.js +227 -160
- package/dist/commands/runtime/index.js +343 -118
- package/dist/commands/shared/help.d.ts +1 -0
- package/dist/commands/shared/help.js +10 -6
- package/dist/commands/shared/operation.d.ts +83 -0
- package/dist/commands/shared/{rest.js → operation.js} +81 -32
- package/dist/commands/space/index.js +62 -68
- package/dist/commands/space/list.d.ts +1 -11
- package/dist/commands/space/list.js +12 -20
- package/dist/commands/subaccount/index.js +56 -125
- package/dist/commands/tool/index.js +28 -22
- package/dist/commands/tool-call/index.js +11 -6
- package/dist/commands/toolset/index.js +16 -15
- package/dist/commands/usage/index.d.ts +3 -0
- package/dist/commands/usage/index.js +13 -0
- package/dist/commands/vault/index.js +115 -34
- package/dist/config/auth-store.d.ts +10 -12
- package/dist/config/auth-store.js +4 -5
- package/dist/generated/help.d.ts +5992 -71
- package/dist/generated/help.js +7918 -123
- package/dist/generated/openapi-routes.d.ts +391 -0
- package/dist/generated/openapi-routes.js +100 -0
- package/dist/generated/openapi-types.d.ts +13755 -0
- package/dist/generated/openapi-types.js +5 -0
- package/dist/openapi.d.ts +20 -0
- package/dist/openapi.js +1 -0
- package/dist/root.js +10 -4
- package/package.json +47 -45
- package/dist/commands/browser/index.js +0 -53
- package/dist/commands/invocation/index.js +0 -36
- package/dist/commands/shared/rest.d.ts +0 -54
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
import { CLI_OPENAPI_ROUTES } from '../../generated/openapi-routes.js';
|
|
1
2
|
import { Command } from 'commander';
|
|
2
|
-
import { CliError } from '../../runtime/errors.js';
|
|
3
3
|
import { readJsonFile } from './io.js';
|
|
4
4
|
import { parsePositiveInteger } from './options.js';
|
|
5
5
|
import { addOutputFlags, outputData } from './output.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
6
|
+
import { CliError } from '../../runtime/errors.js';
|
|
7
|
+
import { addCliOperationHelp } from './help.js';
|
|
9
8
|
export function addPaginationFlags(command) {
|
|
10
9
|
return command
|
|
11
10
|
.option('-L, --limit <number>', 'Maximum number of results to return', parsePositiveInteger)
|
|
@@ -14,72 +13,125 @@ export function addPaginationFlags(command) {
|
|
|
14
13
|
export function addJsonBodyFlag(command) {
|
|
15
14
|
return command.option('--input <path>', 'Read JSON request body from file, or - for stdin');
|
|
16
15
|
}
|
|
17
|
-
export
|
|
16
|
+
export function outputFlags(options) {
|
|
17
|
+
return {
|
|
18
|
+
...(typeof options.json === 'string' || typeof options.json === 'boolean'
|
|
19
|
+
? { json: options.json }
|
|
20
|
+
: {}),
|
|
21
|
+
...(typeof options.jq === 'string' ? { jq: options.jq } : {}),
|
|
22
|
+
...(typeof options.template === 'string' ? { template: options.template } : {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function operationPath(operationId, pathParams) {
|
|
26
|
+
const route = CLI_OPENAPI_ROUTES[operationId];
|
|
27
|
+
return route.path.replace(/\{([^}]+)\}/g, (_match, key) => {
|
|
28
|
+
const value = pathParams?.[key];
|
|
29
|
+
if (value === undefined) {
|
|
30
|
+
throw new Error(`Missing path parameter "${key}" for ${operationId}`);
|
|
31
|
+
}
|
|
32
|
+
return encodeURIComponent(String(value));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export async function requestOperationAndPrint(deps, operationId, input) {
|
|
36
|
+
const result = await requestOperation(deps, operationId, input);
|
|
37
|
+
await outputData(deps.io, result, input.output);
|
|
38
|
+
}
|
|
39
|
+
export async function requestOperation(deps, operationId, input) {
|
|
40
|
+
const route = CLI_OPENAPI_ROUTES[operationId];
|
|
18
41
|
const client = await deps.apiClient();
|
|
19
|
-
const
|
|
42
|
+
const path = operationPath(operationId, input.pathParams);
|
|
43
|
+
const requestOptions = {
|
|
44
|
+
...('query' in input && input.query !== undefined ? { query: input.query } : {}),
|
|
45
|
+
...('body' in input && input.body !== undefined ? { body: input.body } : {}),
|
|
46
|
+
...(input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}),
|
|
47
|
+
};
|
|
48
|
+
const options = Object.keys(requestOptions).length > 0 ? requestOptions : undefined;
|
|
49
|
+
const result = route.method === 'get'
|
|
20
50
|
? await client.get(path, options)
|
|
21
|
-
: method === 'post'
|
|
51
|
+
: route.method === 'post'
|
|
22
52
|
? await client.post(path, options)
|
|
23
|
-
: method === 'patch'
|
|
53
|
+
: route.method === 'patch'
|
|
24
54
|
? await client.patch(path, options)
|
|
25
|
-
: method === 'put'
|
|
55
|
+
: route.method === 'put'
|
|
26
56
|
? await client.put(path, options)
|
|
27
57
|
: await client.delete(path, options);
|
|
28
|
-
|
|
58
|
+
return result;
|
|
29
59
|
}
|
|
30
|
-
export async function
|
|
31
|
-
|
|
60
|
+
export async function uploadOperationFile(deps, operationId, input) {
|
|
61
|
+
const client = await deps.apiClient();
|
|
62
|
+
return client.uploadFile(operationPath(operationId, input.pathParams), {
|
|
63
|
+
file: input.file,
|
|
64
|
+
fileName: input.fileName,
|
|
65
|
+
...('query' in input && input.query !== undefined ? { query: input.query } : {}),
|
|
66
|
+
...(input.fields ? { fields: input.fields } : {}),
|
|
67
|
+
});
|
|
32
68
|
}
|
|
33
|
-
export function
|
|
69
|
+
export async function downloadOperation(deps, operationId, input) {
|
|
70
|
+
const client = await deps.apiClient();
|
|
71
|
+
return client.download(operationPath(operationId, input.pathParams));
|
|
72
|
+
}
|
|
73
|
+
export async function streamOperationText(deps, operationId, input) {
|
|
74
|
+
const client = await deps.apiClient();
|
|
75
|
+
return client.streamText(operationPath(operationId, input.pathParams), {
|
|
76
|
+
...('query' in input && input.query !== undefined ? { query: input.query } : {}),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
export function createOperationListCommand(factory, config) {
|
|
34
80
|
let command = new Command(config.name ?? 'list').description(config.description);
|
|
81
|
+
command = addCliOperationHelp(command, config.operationId);
|
|
35
82
|
command = config.configure ? config.configure(command) : addPaginationFlags(command);
|
|
36
83
|
command = addOutputFlags(command);
|
|
37
84
|
return command.action(async (options) => {
|
|
38
|
-
await
|
|
85
|
+
await requestOperationAndPrint(factory, config.operationId, {
|
|
39
86
|
query: config.query ? config.query(options) : defaultListQuery(options),
|
|
40
87
|
output: outputFlags(options),
|
|
41
88
|
});
|
|
42
89
|
});
|
|
43
90
|
}
|
|
44
|
-
export function
|
|
91
|
+
export function createOperationViewCommand(factory, config) {
|
|
45
92
|
const argName = config.argName ?? 'id';
|
|
46
93
|
let command = new Command(config.name ?? 'view')
|
|
47
94
|
.description(config.description)
|
|
48
95
|
.argument(`<${argName}>`);
|
|
96
|
+
command = addCliOperationHelp(command, config.operationId);
|
|
49
97
|
command = config.configure ? config.configure(command) : command;
|
|
50
98
|
command = addOutputFlags(command);
|
|
51
99
|
return command.action(async (id, options) => {
|
|
52
|
-
await
|
|
100
|
+
await requestOperationAndPrint(factory, config.operationId, {
|
|
101
|
+
pathParams: { [argName]: id, id },
|
|
53
102
|
query: config.query ? config.query(id, options) : undefined,
|
|
54
103
|
output: outputFlags(options),
|
|
55
104
|
});
|
|
56
105
|
});
|
|
57
106
|
}
|
|
58
|
-
export function
|
|
107
|
+
export function createOperationDeleteCommand(factory, config) {
|
|
59
108
|
const argNames = config.argNames ?? ['id'];
|
|
60
109
|
let command = new Command(config.name ?? 'delete').description(config.description);
|
|
110
|
+
command = addCliOperationHelp(command, config.operationId);
|
|
61
111
|
for (const arg of argNames)
|
|
62
112
|
command = command.argument(`<${arg}>`);
|
|
63
113
|
command = command.option('-y, --yes', 'Confirm deletion');
|
|
64
114
|
command = config.configure ? config.configure(command) : command;
|
|
65
115
|
command = addOutputFlags(command);
|
|
66
|
-
return command.action(async (...
|
|
67
|
-
const options = getActionOptions(
|
|
116
|
+
return command.action(async (...actionArgs) => {
|
|
117
|
+
const options = getActionOptions(actionArgs);
|
|
68
118
|
if (options.yes !== true) {
|
|
69
119
|
throw new CliError('Refusing to delete without --yes');
|
|
70
120
|
}
|
|
71
121
|
const params = {};
|
|
72
122
|
for (let i = 0; i < argNames.length; i += 1)
|
|
73
|
-
params[argNames[i]] = String(
|
|
74
|
-
await
|
|
123
|
+
params[argNames[i]] = String(actionArgs[i]);
|
|
124
|
+
await requestOperationAndPrint(factory, config.operationId, {
|
|
125
|
+
pathParams: params,
|
|
75
126
|
query: config.query ? config.query(params, options) : undefined,
|
|
76
127
|
output: outputFlags(options),
|
|
77
128
|
});
|
|
78
129
|
});
|
|
79
130
|
}
|
|
80
|
-
export function
|
|
131
|
+
export function createOperationJsonBodyCommand(factory, config) {
|
|
81
132
|
const argNames = config.argNames ?? [];
|
|
82
133
|
let command = new Command(config.name).description(config.description);
|
|
134
|
+
command = addCliOperationHelp(command, config.operationId);
|
|
83
135
|
for (const arg of argNames)
|
|
84
136
|
command = command.argument(`<${arg}>`);
|
|
85
137
|
command = config.configure ? config.configure(command) : addJsonBodyFlag(command);
|
|
@@ -89,8 +141,11 @@ export function createJsonBodyCommand(factory, config) {
|
|
|
89
141
|
const args = {};
|
|
90
142
|
for (let i = 0; i < argNames.length; i += 1)
|
|
91
143
|
args[argNames[i]] = String(actionArgs[i]);
|
|
92
|
-
const body = config.body
|
|
93
|
-
|
|
144
|
+
const body = config.body
|
|
145
|
+
? await config.body(args, options)
|
|
146
|
+
: await bodyFromInputOption(String(options.input ?? ''));
|
|
147
|
+
await requestOperationAndPrint(factory, config.operationId, {
|
|
148
|
+
pathParams: args,
|
|
94
149
|
body,
|
|
95
150
|
query: config.query ? config.query(args, options) : undefined,
|
|
96
151
|
output: outputFlags(options),
|
|
@@ -103,14 +158,8 @@ function defaultListQuery(options) {
|
|
|
103
158
|
cursor: typeof options.cursor === 'string' ? options.cursor : undefined,
|
|
104
159
|
};
|
|
105
160
|
}
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
...(typeof options.json === 'string' || typeof options.json === 'boolean'
|
|
109
|
-
? { json: options.json }
|
|
110
|
-
: {}),
|
|
111
|
-
...(typeof options.jq === 'string' ? { jq: options.jq } : {}),
|
|
112
|
-
...(typeof options.template === 'string' ? { template: options.template } : {}),
|
|
113
|
-
};
|
|
161
|
+
async function bodyFromInputOption(path) {
|
|
162
|
+
return path ? readJsonFile(path) : {};
|
|
114
163
|
}
|
|
115
164
|
function getActionOptions(args) {
|
|
116
165
|
const candidate = args.at(-2);
|
|
@@ -1,86 +1,80 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { createJsonBodyCommand, createViewCommand } from '../shared/rest.js';
|
|
3
2
|
import { readJsonFile } from '../shared/io.js';
|
|
4
|
-
import {
|
|
3
|
+
import { outputFlags, requestOperationAndPrint } from '../shared/operation.js';
|
|
4
|
+
import { addOutputFlags } from '../shared/output.js';
|
|
5
|
+
import { CliError } from '../../runtime/errors.js';
|
|
5
6
|
import { createSpaceListCommand } from './list.js';
|
|
6
7
|
export function createSpaceCommand(factory) {
|
|
7
8
|
const command = new Command('space').description('Manage BCTRL spaces');
|
|
8
9
|
command.addCommand(createSpaceListCommand(factory));
|
|
9
|
-
command.addCommand(
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
command.addCommand(addOutputFlags(new Command('get').description('View a space').argument('<spaceId>')).action(async (spaceId, options) => {
|
|
11
|
+
await requestOperationAndPrint(factory, 'spaces.get', {
|
|
12
|
+
pathParams: { spaceId },
|
|
13
|
+
output: outputFlags(options),
|
|
14
|
+
});
|
|
12
15
|
}));
|
|
13
|
-
command.addCommand(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
path
|
|
18
|
-
|
|
19
|
-
.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
name: options.name,
|
|
28
|
-
region: options.region,
|
|
29
|
-
subaccountId: options.subaccountId,
|
|
30
|
-
};
|
|
31
|
-
},
|
|
16
|
+
command.addCommand(addOutputFlags(new Command('create')
|
|
17
|
+
.description('Create a space')
|
|
18
|
+
.option('--name <name>', 'Space name')
|
|
19
|
+
.option('--subaccount-id <id>', 'Subaccount id')
|
|
20
|
+
.option('--input <path>', 'Read JSON request body from file, or - for stdin')).action(async (options) => {
|
|
21
|
+
await requestOperationAndPrint(factory, 'spaces.create', {
|
|
22
|
+
body: typeof options.input === 'string'
|
|
23
|
+
? (await readJsonFile(options.input))
|
|
24
|
+
: {
|
|
25
|
+
name: options.name,
|
|
26
|
+
subaccountId: options.subaccountId,
|
|
27
|
+
},
|
|
28
|
+
output: outputFlags(options),
|
|
29
|
+
});
|
|
32
30
|
}));
|
|
33
|
-
command.addCommand(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
path
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
command.addCommand(addOutputFlags(new Command('patch')
|
|
32
|
+
.description('Edit a space')
|
|
33
|
+
.argument('<spaceId>')
|
|
34
|
+
.option('--name <name>', 'Space name')
|
|
35
|
+
.option('--input <path>', 'Read JSON request body from file, or - for stdin')).action(async (spaceId, options) => {
|
|
36
|
+
await requestOperationAndPrint(factory, 'spaces.update', {
|
|
37
|
+
pathParams: { spaceId },
|
|
38
|
+
body: typeof options.input === 'string'
|
|
39
|
+
? (await readJsonFile(options.input))
|
|
40
|
+
: { name: options.name },
|
|
41
|
+
output: outputFlags(options),
|
|
42
|
+
});
|
|
43
|
+
}));
|
|
44
|
+
command.addCommand(addOutputFlags(new Command('delete')
|
|
45
|
+
.description('Delete a space')
|
|
46
|
+
.argument('<spaceId>')
|
|
47
|
+
.option('-y, --yes', 'Confirm deletion')).action(async (spaceId, options) => {
|
|
48
|
+
if (options.yes !== true) {
|
|
49
|
+
throw new CliError('Refusing to delete without --yes');
|
|
50
|
+
}
|
|
51
|
+
await requestOperationAndPrint(factory, 'spaces.delete', {
|
|
52
|
+
pathParams: { spaceId },
|
|
53
|
+
output: outputFlags(options),
|
|
54
|
+
});
|
|
47
55
|
}));
|
|
48
56
|
command.addCommand(createSpaceEnvironmentCommand(factory));
|
|
49
|
-
command.addCommand(createSpaceAgentContextCommand(factory));
|
|
50
57
|
return command;
|
|
51
58
|
}
|
|
52
59
|
function createSpaceEnvironmentCommand(factory) {
|
|
53
60
|
const command = new Command('env').description('Manage a space environment');
|
|
54
|
-
command.addCommand(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
command.addCommand(addOutputFlags(new Command('get').description('Get a space environment').argument('<spaceId>')).action(async (spaceId, options) => {
|
|
62
|
+
await requestOperationAndPrint(factory, 'spaces.environment.get', {
|
|
63
|
+
pathParams: { spaceId },
|
|
64
|
+
output: outputFlags(options),
|
|
65
|
+
});
|
|
58
66
|
}));
|
|
59
|
-
command.addCommand(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
command.addCommand(addOutputFlags(new Command('patch')
|
|
68
|
+
.description('Update a space environment')
|
|
69
|
+
.argument('<spaceId>')
|
|
70
|
+
.option('--input <path>', 'Read JSON request body from file, or - for stdin')).action(async (spaceId, options) => {
|
|
71
|
+
await requestOperationAndPrint(factory, 'spaces.environment.update', {
|
|
72
|
+
pathParams: { spaceId },
|
|
73
|
+
body: typeof options.input === 'string'
|
|
74
|
+
? (await readJsonFile(options.input))
|
|
75
|
+
: {},
|
|
76
|
+
output: outputFlags(options),
|
|
77
|
+
});
|
|
65
78
|
}));
|
|
66
79
|
return command;
|
|
67
80
|
}
|
|
68
|
-
function createSpaceAgentContextCommand(factory) {
|
|
69
|
-
return addOutputFlags(new Command('agent-context')
|
|
70
|
-
.description('Get machine-readable context for coding agents')
|
|
71
|
-
.argument('<id>')
|
|
72
|
-
.option('--runtime <id>', 'Runtime id')
|
|
73
|
-
.option('--topic <topic>', 'Context topic')
|
|
74
|
-
.option('--detail <level>', 'Detail level'))
|
|
75
|
-
.action(async (id, options) => {
|
|
76
|
-
const client = await factory.apiClient();
|
|
77
|
-
const result = await client.get(`/spaces/${encodeURIComponent(id)}/agent-context`, {
|
|
78
|
-
query: {
|
|
79
|
-
runtimeId: options.runtime,
|
|
80
|
-
topic: options.topic,
|
|
81
|
-
detail: options.detail,
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
await outputData(factory.io, result, options);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
@@ -1,13 +1,3 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import type { BctrlApiClient } from '../../api/client.js';
|
|
3
2
|
import type { Factory } from '../../factory.js';
|
|
4
|
-
|
|
5
|
-
import { type OutputFlags } from '../shared/output.js';
|
|
6
|
-
export type SpaceListOptions = {
|
|
7
|
-
io: IOStreams;
|
|
8
|
-
apiClient: () => Promise<BctrlApiClient>;
|
|
9
|
-
limit?: number;
|
|
10
|
-
output?: OutputFlags;
|
|
11
|
-
};
|
|
12
|
-
export declare function createSpaceListCommand(factory: Factory, run?: (options: SpaceListOptions) => Promise<void>): Command;
|
|
13
|
-
export declare function spaceListRun(options: SpaceListOptions): Promise<void>;
|
|
3
|
+
export declare function createSpaceListCommand(factory: Factory): Command;
|
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { addPaginationFlags, outputFlags, requestOperationAndPrint } from '../shared/operation.js';
|
|
3
|
+
import { addOutputFlags } from '../shared/output.js';
|
|
4
|
+
export function createSpaceListCommand(factory) {
|
|
5
|
+
return addOutputFlags(addPaginationFlags(new Command('list')
|
|
5
6
|
.description('List spaces')
|
|
6
|
-
.option('--
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
.option('--subaccount <id>', 'Filter by subaccount id'))).action(async (options) => {
|
|
8
|
+
await requestOperationAndPrint(factory, 'spaces.list', {
|
|
9
|
+
query: {
|
|
10
|
+
subaccountId: options.subaccount,
|
|
11
|
+
limit: options.limit,
|
|
12
|
+
cursor: options.cursor,
|
|
13
|
+
},
|
|
14
|
+
output: outputFlags(options),
|
|
13
15
|
});
|
|
14
16
|
});
|
|
15
17
|
}
|
|
16
|
-
export async function spaceListRun(options) {
|
|
17
|
-
const client = await options.apiClient();
|
|
18
|
-
const result = await client.get('/spaces', {
|
|
19
|
-
query: {
|
|
20
|
-
limit: options.limit,
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
await outputData(options.io, result, options.output);
|
|
24
|
-
}
|
|
25
|
-
import { parsePositiveInteger } from '../shared/options.js';
|
|
@@ -2,54 +2,65 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { readJsonFile } from '../shared/io.js';
|
|
3
3
|
import { parsePositiveInteger } from '../shared/options.js';
|
|
4
4
|
import { addOutputFlags } from '../shared/output.js';
|
|
5
|
-
import {
|
|
5
|
+
import { addPaginationFlags, createOperationJsonBodyCommand, createOperationListCommand, createOperationViewCommand, outputFlags, requestOperationAndPrint, } from '../shared/operation.js';
|
|
6
6
|
export function createSubaccountCommand(factory) {
|
|
7
|
-
const command = new Command('subaccount').description('Manage subaccounts
|
|
8
|
-
command.addCommand(
|
|
7
|
+
const command = new Command('subaccount').description('Manage subaccounts');
|
|
8
|
+
command.addCommand(createOperationListCommand(factory, {
|
|
9
|
+
operationId: 'subaccounts.list',
|
|
9
10
|
description: 'List subaccounts',
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
query: (options) => ({
|
|
12
|
+
limit: typeof options.limit === 'number' ? options.limit : undefined,
|
|
13
|
+
cursor: typeof options.cursor === 'string' ? options.cursor : undefined,
|
|
14
|
+
include: options.includeUsage === true ? 'usage' : undefined,
|
|
15
|
+
status: typeof options.status === 'string' ? options.status : undefined,
|
|
16
|
+
externalId: typeof options.externalId === 'string' ? options.externalId : undefined,
|
|
17
|
+
query: typeof options.query === 'string' ? options.query : undefined,
|
|
18
|
+
}),
|
|
19
|
+
configure: (cmd) => addPaginationFlags(cmd)
|
|
20
|
+
.option('--include-usage', 'Inline current usage')
|
|
21
|
+
.option('--status <status>', 'Filter by status')
|
|
22
|
+
.option('--external-id <id>', 'Filter by external id')
|
|
23
|
+
.option('--query <text>', 'Search by id, name, or external id'),
|
|
12
24
|
}));
|
|
13
|
-
command.addCommand(
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
command.addCommand(createOperationViewCommand(factory, {
|
|
26
|
+
operationId: 'subaccounts.get',
|
|
27
|
+
name: 'get',
|
|
28
|
+
description: 'Get a subaccount',
|
|
29
|
+
argName: 'subaccountId',
|
|
30
|
+
configure: (cmd) => cmd.option('--include <value>', 'Include related data, for example usage'),
|
|
31
|
+
query: (_id, options) => ({
|
|
32
|
+
include: typeof options.include === 'string' ? options.include : undefined,
|
|
33
|
+
}),
|
|
16
34
|
}));
|
|
17
|
-
command.addCommand(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
body: async (_args, options) => {
|
|
28
|
-
if (typeof options.input === 'string')
|
|
29
|
-
return readJsonFile(options.input);
|
|
30
|
-
return {
|
|
31
|
-
name: options.name,
|
|
32
|
-
externalId: options.externalId,
|
|
33
|
-
metadata: typeof options.metadataFile === 'string'
|
|
34
|
-
? await readJsonFile(options.metadataFile, '--metadata-file')
|
|
35
|
-
: undefined,
|
|
36
|
-
};
|
|
37
|
-
},
|
|
35
|
+
command.addCommand(createSubaccountWriteCommand(factory, 'create', 'subaccounts.create'));
|
|
36
|
+
command.addCommand(createSubaccountWriteCommand(factory, 'patch', 'subaccounts.update', ['subaccountId']));
|
|
37
|
+
command.addCommand(addOutputFlags(new Command('archive')
|
|
38
|
+
.description('Archive a subaccount')
|
|
39
|
+
.argument('<subaccountId>')
|
|
40
|
+
.requiredOption('-y, --yes', 'Confirm archive')).action(async (subaccountId, options) => {
|
|
41
|
+
await requestOperationAndPrint(factory, 'subaccounts.archive', {
|
|
42
|
+
pathParams: { subaccountId },
|
|
43
|
+
output: outputFlags(options),
|
|
44
|
+
});
|
|
38
45
|
}));
|
|
39
|
-
command.addCommand(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
command.addCommand(createSubaccountUsageCommand(factory));
|
|
47
|
+
return command;
|
|
48
|
+
}
|
|
49
|
+
function createSubaccountWriteCommand(factory, name, operationId, argNames = []) {
|
|
50
|
+
return createOperationJsonBodyCommand(factory, {
|
|
51
|
+
operationId,
|
|
52
|
+
name,
|
|
53
|
+
description: name === 'create' ? 'Create a subaccount' : 'Update a subaccount',
|
|
54
|
+
argNames,
|
|
45
55
|
configure: (cmd) => cmd
|
|
46
56
|
.option('--name <name>', 'Subaccount name')
|
|
47
57
|
.option('--external-id <id>', 'External id')
|
|
48
58
|
.option('--metadata-file <path>', 'Metadata JSON file')
|
|
49
59
|
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
50
60
|
body: async (_args, options) => {
|
|
51
|
-
if (typeof options.input === 'string')
|
|
52
|
-
return readJsonFile(options.input);
|
|
61
|
+
if (typeof options.input === 'string') {
|
|
62
|
+
return (await readJsonFile(options.input));
|
|
63
|
+
}
|
|
53
64
|
return {
|
|
54
65
|
name: options.name,
|
|
55
66
|
externalId: options.externalId,
|
|
@@ -58,105 +69,25 @@ export function createSubaccountCommand(factory) {
|
|
|
58
69
|
: undefined,
|
|
59
70
|
};
|
|
60
71
|
},
|
|
61
|
-
})
|
|
62
|
-
command.addCommand(addOutputFlags(new Command('archive')
|
|
63
|
-
.description('Archive a subaccount')
|
|
64
|
-
.argument('<id>')
|
|
65
|
-
.requiredOption('-y, --yes', 'Confirm archive'))
|
|
66
|
-
.action(async (id, options) => {
|
|
67
|
-
await requestAndPrint(factory, 'post', `/subaccounts/${encodeURIComponent(id)}/archive`, {
|
|
68
|
-
output: options,
|
|
69
|
-
});
|
|
70
|
-
}));
|
|
71
|
-
command.addCommand(createSubaccountUsageCommand(factory));
|
|
72
|
-
command.addCommand(createSubaccountLimitsCommand(factory));
|
|
73
|
-
command.addCommand(createSubaccountKeyCommand(factory));
|
|
74
|
-
return command;
|
|
72
|
+
});
|
|
75
73
|
}
|
|
76
74
|
function createSubaccountUsageCommand(factory) {
|
|
77
75
|
return addOutputFlags(new Command('usage')
|
|
78
76
|
.description('Show subaccount usage')
|
|
79
77
|
.argument('[id]')
|
|
80
78
|
.option('-L, --limit <number>', 'Maximum number of usage records to return', parsePositiveInteger)
|
|
81
|
-
.option('--cursor <cursor>', 'Pagination cursor'))
|
|
82
|
-
.action(async (id, options) => {
|
|
79
|
+
.option('--cursor <cursor>', 'Pagination cursor')).action(async (id, options) => {
|
|
83
80
|
if (id) {
|
|
84
|
-
await
|
|
85
|
-
|
|
81
|
+
await requestOperationAndPrint(factory, 'subaccounts.get', {
|
|
82
|
+
pathParams: { subaccountId: id },
|
|
83
|
+
query: { include: 'usage' },
|
|
84
|
+
output: outputFlags(options),
|
|
86
85
|
});
|
|
87
86
|
return;
|
|
88
87
|
}
|
|
89
|
-
await
|
|
88
|
+
await requestOperationAndPrint(factory, 'subaccounts.usage.list', {
|
|
90
89
|
query: { limit: options.limit, cursor: options.cursor },
|
|
91
|
-
output: options,
|
|
90
|
+
output: outputFlags(options),
|
|
92
91
|
});
|
|
93
92
|
});
|
|
94
93
|
}
|
|
95
|
-
function createSubaccountLimitsCommand(factory) {
|
|
96
|
-
const command = new Command('limits').description('Manage subaccount limits');
|
|
97
|
-
command.addCommand(addOutputFlags(new Command('get')
|
|
98
|
-
.description('View subaccount limits')
|
|
99
|
-
.argument('<id>'))
|
|
100
|
-
.action(async (id, options) => {
|
|
101
|
-
await requestAndPrint(factory, 'get', `/subaccounts/${encodeURIComponent(id)}/limits`, {
|
|
102
|
-
output: options,
|
|
103
|
-
});
|
|
104
|
-
}));
|
|
105
|
-
command.addCommand(createJsonBodyCommand(factory, {
|
|
106
|
-
name: 'set',
|
|
107
|
-
description: 'Update subaccount limits',
|
|
108
|
-
method: 'patch',
|
|
109
|
-
path: '/subaccounts/{id}/limits',
|
|
110
|
-
argNames: ['id'],
|
|
111
|
-
configure: (cmd) => cmd
|
|
112
|
-
.option('--max-spaces <number>', 'Maximum spaces')
|
|
113
|
-
.option('--max-active-runs <number>', 'Maximum active runs')
|
|
114
|
-
.option('--monthly-spend-micro-usd <number>', 'Monthly spend limit in micro USD')
|
|
115
|
-
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
116
|
-
body: async (_args, options) => {
|
|
117
|
-
if (typeof options.input === 'string')
|
|
118
|
-
return readJsonFile(options.input);
|
|
119
|
-
return {
|
|
120
|
-
spaces: options.maxSpaces ? { max: Number(options.maxSpaces) } : undefined,
|
|
121
|
-
runs: options.maxActiveRuns ? { maxActive: Number(options.maxActiveRuns) } : undefined,
|
|
122
|
-
spend: options.monthlySpendMicroUsd
|
|
123
|
-
? { monthlyLimitMicroUsd: Number(options.monthlySpendMicroUsd) }
|
|
124
|
-
: undefined,
|
|
125
|
-
};
|
|
126
|
-
},
|
|
127
|
-
}));
|
|
128
|
-
return command;
|
|
129
|
-
}
|
|
130
|
-
function createSubaccountKeyCommand(factory) {
|
|
131
|
-
const command = new Command('key').description('Manage subaccount API keys');
|
|
132
|
-
command.addCommand(addOutputFlags(new Command('list')
|
|
133
|
-
.description('List subaccount API keys')
|
|
134
|
-
.argument('<id>'))
|
|
135
|
-
.action(async (id, options) => {
|
|
136
|
-
await requestAndPrint(factory, 'get', `/subaccounts/${encodeURIComponent(id)}/api-keys`, {
|
|
137
|
-
output: options,
|
|
138
|
-
});
|
|
139
|
-
}));
|
|
140
|
-
command.addCommand(createJsonBodyCommand(factory, {
|
|
141
|
-
name: 'create',
|
|
142
|
-
description: 'Create a subaccount API key',
|
|
143
|
-
method: 'post',
|
|
144
|
-
path: '/subaccounts/{id}/api-keys',
|
|
145
|
-
argNames: ['id'],
|
|
146
|
-
configure: (cmd) => cmd
|
|
147
|
-
.option('--name <name>', 'API key name')
|
|
148
|
-
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
149
|
-
body: async (_args, options) => {
|
|
150
|
-
if (typeof options.input === 'string')
|
|
151
|
-
return readJsonFile(options.input);
|
|
152
|
-
return { name: options.name };
|
|
153
|
-
},
|
|
154
|
-
}));
|
|
155
|
-
command.addCommand(createDeleteCommand(factory, {
|
|
156
|
-
name: 'revoke',
|
|
157
|
-
description: 'Revoke a subaccount API key',
|
|
158
|
-
path: '/subaccounts/{id}/api-keys/{keyId}',
|
|
159
|
-
argNames: ['id', 'keyId'],
|
|
160
|
-
}));
|
|
161
|
-
return command;
|
|
162
|
-
}
|