@bctrl/cli 0.1.3 → 0.1.4
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 +59 -102
- 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 +86 -0
- package/dist/commands/file/index.js +9 -3
- 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 +66 -0
- package/dist/commands/run/index.js +205 -155
- package/dist/commands/runtime/index.js +274 -78
- package/dist/commands/shared/help.js +1 -1
- package/dist/commands/shared/rest.d.ts +1 -0
- package/dist/commands/shared/rest.js +14 -6
- package/dist/commands/space/index.js +17 -32
- package/dist/commands/space/list.d.ts +1 -11
- package/dist/commands/space/list.js +14 -23
- package/dist/commands/subaccount/index.js +29 -80
- package/dist/commands/tool/index.js +15 -7
- package/dist/commands/tool-call/index.js +6 -1
- package/dist/commands/toolset/index.js +6 -3
- package/dist/commands/usage/index.d.ts +3 -0
- package/dist/commands/usage/index.js +13 -0
- package/dist/commands/vault/index.js +104 -25
- package/dist/config/auth-store.d.ts +10 -12
- package/dist/config/auth-store.js +4 -5
- package/dist/generated/help.d.ts +132 -46
- package/dist/generated/help.js +192 -54
- 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
|
@@ -2,17 +2,35 @@ 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 { createJsonBodyCommand, addPaginationFlags, createListCommand, createViewCommand, requestAndPrint, } from '../shared/rest.js';
|
|
6
6
|
export function createSubaccountCommand(factory) {
|
|
7
|
-
const command = new Command('subaccount').description('Manage subaccounts
|
|
7
|
+
const command = new Command('subaccount').description('Manage subaccounts');
|
|
8
8
|
command.addCommand(createListCommand(factory, {
|
|
9
9
|
description: 'List subaccounts',
|
|
10
10
|
path: '/subaccounts',
|
|
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
25
|
command.addCommand(createViewCommand(factory, {
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
name: 'get',
|
|
27
|
+
description: 'Get a subaccount',
|
|
28
|
+
path: '/subaccounts/{subaccountId}',
|
|
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
35
|
command.addCommand(createJsonBodyCommand(factory, {
|
|
18
36
|
name: 'create',
|
|
@@ -37,11 +55,11 @@ export function createSubaccountCommand(factory) {
|
|
|
37
55
|
},
|
|
38
56
|
}));
|
|
39
57
|
command.addCommand(createJsonBodyCommand(factory, {
|
|
40
|
-
name: '
|
|
41
|
-
description: '
|
|
58
|
+
name: 'patch',
|
|
59
|
+
description: 'Update a subaccount',
|
|
42
60
|
method: 'patch',
|
|
43
|
-
path: '/subaccounts/{
|
|
44
|
-
argNames: ['
|
|
61
|
+
path: '/subaccounts/{subaccountId}',
|
|
62
|
+
argNames: ['subaccountId'],
|
|
45
63
|
configure: (cmd) => cmd
|
|
46
64
|
.option('--name <name>', 'Subaccount name')
|
|
47
65
|
.option('--external-id <id>', 'External id')
|
|
@@ -69,8 +87,6 @@ export function createSubaccountCommand(factory) {
|
|
|
69
87
|
});
|
|
70
88
|
}));
|
|
71
89
|
command.addCommand(createSubaccountUsageCommand(factory));
|
|
72
|
-
command.addCommand(createSubaccountLimitsCommand(factory));
|
|
73
|
-
command.addCommand(createSubaccountKeyCommand(factory));
|
|
74
90
|
return command;
|
|
75
91
|
}
|
|
76
92
|
function createSubaccountUsageCommand(factory) {
|
|
@@ -81,7 +97,8 @@ function createSubaccountUsageCommand(factory) {
|
|
|
81
97
|
.option('--cursor <cursor>', 'Pagination cursor'))
|
|
82
98
|
.action(async (id, options) => {
|
|
83
99
|
if (id) {
|
|
84
|
-
await requestAndPrint(factory, 'get', `/subaccounts/${encodeURIComponent(id)}
|
|
100
|
+
await requestAndPrint(factory, 'get', `/subaccounts/${encodeURIComponent(id)}`, {
|
|
101
|
+
query: { include: 'usage' },
|
|
85
102
|
output: options,
|
|
86
103
|
});
|
|
87
104
|
return;
|
|
@@ -92,71 +109,3 @@ function createSubaccountUsageCommand(factory) {
|
|
|
92
109
|
});
|
|
93
110
|
});
|
|
94
111
|
}
|
|
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
|
-
}
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { createDeleteCommand, createJsonBodyCommand, createListCommand, createViewCommand } from '../shared/rest.js';
|
|
2
|
+
import { createDeleteCommand, createJsonBodyCommand, createListCommand, createViewCommand, } from '../shared/rest.js';
|
|
3
3
|
export function createToolCommand(factory) {
|
|
4
|
-
const command = new Command('tool').description('Manage
|
|
4
|
+
const command = new Command('tool').description('Manage tools');
|
|
5
5
|
command.addCommand(createListCommand(factory, {
|
|
6
6
|
description: 'List tools',
|
|
7
7
|
path: '/tools',
|
|
8
|
-
configure: (cmd) => cmd
|
|
9
|
-
|
|
8
|
+
configure: (cmd) => cmd
|
|
9
|
+
.option('--space <id>', 'Filter by space id')
|
|
10
|
+
.option('--query <text>', 'Search tools')
|
|
11
|
+
.option('--status <status>', 'Filter by status'),
|
|
12
|
+
query: (options) => ({
|
|
13
|
+
spaceId: typeof options.space === 'string' ? options.space : undefined,
|
|
14
|
+
query: typeof options.query === 'string' ? options.query : undefined,
|
|
15
|
+
status: typeof options.status === 'string' ? options.status : undefined,
|
|
16
|
+
}),
|
|
10
17
|
}));
|
|
11
18
|
command.addCommand(createViewCommand(factory, {
|
|
12
|
-
|
|
19
|
+
name: 'get',
|
|
20
|
+
description: 'Get a tool',
|
|
13
21
|
path: '/tools/{id}',
|
|
14
22
|
}));
|
|
15
23
|
command.addCommand(createJsonBodyCommand(factory, {
|
|
@@ -19,8 +27,8 @@ export function createToolCommand(factory) {
|
|
|
19
27
|
path: '/tools',
|
|
20
28
|
}));
|
|
21
29
|
command.addCommand(createJsonBodyCommand(factory, {
|
|
22
|
-
name: '
|
|
23
|
-
description: '
|
|
30
|
+
name: 'patch',
|
|
31
|
+
description: 'Update a tool',
|
|
24
32
|
method: 'patch',
|
|
25
33
|
path: '/tools/{id}',
|
|
26
34
|
argNames: ['id'],
|
|
@@ -6,18 +6,23 @@ export function createToolCallCommand(factory) {
|
|
|
6
6
|
description: 'List tool calls',
|
|
7
7
|
path: '/tool-calls',
|
|
8
8
|
configure: (cmd) => cmd
|
|
9
|
+
.option('--space <id>', 'Space id')
|
|
9
10
|
.option('--tool <id>', 'Filter by tool id')
|
|
10
11
|
.option('--run <id>', 'Filter by run id')
|
|
11
12
|
.option('--invocation <id>', 'Filter by invocation id')
|
|
12
|
-
.option('--status <status>', 'Filter by status')
|
|
13
|
+
.option('--status <status>', 'Filter by status')
|
|
14
|
+
.option('--actor <actor>', 'Filter by actor'),
|
|
13
15
|
query: (options) => ({
|
|
16
|
+
spaceId: typeof options.space === 'string' ? options.space : undefined,
|
|
14
17
|
toolId: typeof options.tool === 'string' ? options.tool : undefined,
|
|
15
18
|
runId: typeof options.run === 'string' ? options.run : undefined,
|
|
16
19
|
invocationId: typeof options.invocation === 'string' ? options.invocation : undefined,
|
|
17
20
|
status: typeof options.status === 'string' ? options.status : undefined,
|
|
21
|
+
actor: typeof options.actor === 'string' ? options.actor : undefined,
|
|
18
22
|
}),
|
|
19
23
|
}));
|
|
20
24
|
command.addCommand(createViewCommand(factory, {
|
|
25
|
+
name: 'get',
|
|
21
26
|
description: 'View a tool call',
|
|
22
27
|
path: '/tool-calls/{id}',
|
|
23
28
|
}));
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { createDeleteCommand, createJsonBodyCommand, createListCommand, createViewCommand } from '../shared/rest.js';
|
|
2
|
+
import { createDeleteCommand, createJsonBodyCommand, createListCommand, createViewCommand, } from '../shared/rest.js';
|
|
3
3
|
export function createToolsetCommand(factory) {
|
|
4
4
|
const command = new Command('toolset').description('Manage BCTRL toolsets');
|
|
5
5
|
command.addCommand(createListCommand(factory, {
|
|
6
6
|
description: 'List toolsets',
|
|
7
7
|
path: '/toolsets',
|
|
8
8
|
configure: (cmd) => cmd.option('--space <id>', 'Filter by space id'),
|
|
9
|
-
query: (options) => ({
|
|
9
|
+
query: (options) => ({
|
|
10
|
+
spaceId: typeof options.space === 'string' ? options.space : undefined,
|
|
11
|
+
}),
|
|
10
12
|
}));
|
|
11
13
|
command.addCommand(createViewCommand(factory, {
|
|
14
|
+
name: 'get',
|
|
12
15
|
description: 'View a toolset',
|
|
13
16
|
path: '/toolsets/{id}',
|
|
14
17
|
}));
|
|
@@ -19,7 +22,7 @@ export function createToolsetCommand(factory) {
|
|
|
19
22
|
path: '/toolsets',
|
|
20
23
|
}));
|
|
21
24
|
command.addCommand(createJsonBodyCommand(factory, {
|
|
22
|
-
name: '
|
|
25
|
+
name: 'patch',
|
|
23
26
|
description: 'Edit a toolset',
|
|
24
27
|
method: 'patch',
|
|
25
28
|
path: '/toolsets/{id}',
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { addOutputFlags } from '../shared/output.js';
|
|
3
|
+
import { requestAndPrint } from '../shared/rest.js';
|
|
4
|
+
export function createUsageCommand(factory) {
|
|
5
|
+
const command = addOutputFlags(new Command('usage').description('Get organization usage'));
|
|
6
|
+
command.action(async (options) => {
|
|
7
|
+
await requestAndPrint(factory, 'get', '/usage', { output: options });
|
|
8
|
+
});
|
|
9
|
+
command.addCommand(addOutputFlags(new Command('get').description('Get organization usage')).action(async (options) => {
|
|
10
|
+
await requestAndPrint(factory, 'get', '/usage', { output: options });
|
|
11
|
+
}));
|
|
12
|
+
return command;
|
|
13
|
+
}
|
|
@@ -3,14 +3,14 @@ import { CliError } from '../../runtime/errors.js';
|
|
|
3
3
|
import { readJsonFile, readText } from '../shared/io.js';
|
|
4
4
|
import { parsePositiveInteger } from '../shared/options.js';
|
|
5
5
|
import { addOutputFlags } from '../shared/output.js';
|
|
6
|
-
import { createDeleteCommand, createJsonBodyCommand, createListCommand, createViewCommand, requestAndPrint, } from '../shared/rest.js';
|
|
6
|
+
import { createDeleteCommand, createJsonBodyCommand, createListCommand, createViewCommand, pathTemplate, requestAndPrint, } from '../shared/rest.js';
|
|
7
7
|
export function createVaultCommand(factory) {
|
|
8
8
|
const command = new Command('vault').description('Manage vault secrets and TOTP codes');
|
|
9
9
|
command.addCommand(createListCommand(factory, {
|
|
10
10
|
description: 'List vault secret metadata',
|
|
11
11
|
path: '/vault/secrets',
|
|
12
12
|
configure: (cmd) => cmd
|
|
13
|
-
.option('--prefix <prefix>', 'Filter by secret
|
|
13
|
+
.option('--prefix <prefix>', 'Filter by secret key prefix')
|
|
14
14
|
.option('--origin <origin>', 'Filter by origin')
|
|
15
15
|
.option('--has-totp', 'Only show secrets with TOTP')
|
|
16
16
|
.option('-L, --limit <number>', 'Maximum number of results to return', parsePositiveInteger),
|
|
@@ -22,14 +22,18 @@ export function createVaultCommand(factory) {
|
|
|
22
22
|
}),
|
|
23
23
|
}));
|
|
24
24
|
command.addCommand(createViewCommand(factory, {
|
|
25
|
+
name: 'get',
|
|
25
26
|
description: 'View vault secret metadata',
|
|
26
|
-
path: '/vault/secrets/{
|
|
27
|
+
path: '/vault/secrets/{key}',
|
|
28
|
+
argName: 'key',
|
|
27
29
|
}));
|
|
28
30
|
command.addCommand(createVaultReadCommand(factory));
|
|
29
31
|
command.addCommand(createVaultSetCommand(factory));
|
|
32
|
+
command.addCommand(createVaultPatchCommand(factory));
|
|
30
33
|
command.addCommand(createDeleteCommand(factory, {
|
|
31
34
|
description: 'Delete a vault secret',
|
|
32
|
-
path: '/vault/secrets/{
|
|
35
|
+
path: '/vault/secrets/{key}',
|
|
36
|
+
argNames: ['key'],
|
|
33
37
|
}));
|
|
34
38
|
command.addCommand(createVaultTotpCommand(factory));
|
|
35
39
|
return command;
|
|
@@ -37,13 +41,12 @@ export function createVaultCommand(factory) {
|
|
|
37
41
|
function createVaultReadCommand(factory) {
|
|
38
42
|
return addOutputFlags(new Command('read')
|
|
39
43
|
.description('Read a vault secret value')
|
|
40
|
-
.argument('<
|
|
41
|
-
.option('--reveal', 'Allow printing a secret to an interactive terminal'))
|
|
42
|
-
.action(async (id, options) => {
|
|
44
|
+
.argument('<key>')
|
|
45
|
+
.option('--reveal', 'Allow printing a secret to an interactive terminal')).action(async (key, options) => {
|
|
43
46
|
if (factory.io.isStdoutTTY() && options.reveal !== true) {
|
|
44
47
|
throw new CliError('Refusing to print a secret to a terminal without --reveal');
|
|
45
48
|
}
|
|
46
|
-
await requestAndPrint(factory, 'get', `/vault/secrets/${encodeURIComponent(
|
|
49
|
+
await requestAndPrint(factory, 'get', `/vault/secrets/${encodeURIComponent(key)}/value`, {
|
|
47
50
|
output: options,
|
|
48
51
|
});
|
|
49
52
|
});
|
|
@@ -53,13 +56,16 @@ function createVaultSetCommand(factory) {
|
|
|
53
56
|
name: 'set',
|
|
54
57
|
description: 'Create or replace a vault secret',
|
|
55
58
|
method: 'put',
|
|
56
|
-
path: '/vault/secrets',
|
|
57
|
-
argNames: ['
|
|
59
|
+
path: '/vault/secrets/{key}',
|
|
60
|
+
argNames: ['key'],
|
|
58
61
|
configure: (cmd) => cmd
|
|
62
|
+
.option('--type <type>', 'Secret type: login or value')
|
|
63
|
+
.option('--value <value>', 'Generic secret value')
|
|
64
|
+
.option('--value-from-file <path>', 'Read generic secret value from file, or - for stdin')
|
|
59
65
|
.option('--username <value>', 'Credential username')
|
|
60
66
|
.option('--password <value>', 'Credential password')
|
|
61
67
|
.option('--password-from-file <path>', 'Read password from file, or - for stdin')
|
|
62
|
-
.option('--totp <secret>', 'TOTP seed')
|
|
68
|
+
.option('--totp-secret <secret>', 'TOTP seed')
|
|
63
69
|
.option('--label <label>', 'Display label')
|
|
64
70
|
.option('--origin <origin...>', 'Allowed origin')
|
|
65
71
|
.option('--origin-pattern <pattern...>', 'Allowed origin pattern')
|
|
@@ -70,27 +76,100 @@ function createVaultSetCommand(factory) {
|
|
|
70
76
|
const password = typeof options.passwordFromFile === 'string'
|
|
71
77
|
? (await readText(options.passwordFromFile)).trimEnd()
|
|
72
78
|
: options.password;
|
|
79
|
+
const value = typeof options.valueFromFile === 'string'
|
|
80
|
+
? (await readText(options.valueFromFile)).trimEnd()
|
|
81
|
+
: options.value;
|
|
82
|
+
const common = {
|
|
83
|
+
label: options.label,
|
|
84
|
+
origins: options.origin,
|
|
85
|
+
originPatterns: options.originPattern,
|
|
86
|
+
};
|
|
87
|
+
const type = options.type === 'value' || options.type === 'login'
|
|
88
|
+
? options.type
|
|
89
|
+
: typeof value === 'string'
|
|
90
|
+
? 'value'
|
|
91
|
+
: 'login';
|
|
92
|
+
if (typeof options.type === 'string' &&
|
|
93
|
+
options.type !== 'value' &&
|
|
94
|
+
options.type !== 'login') {
|
|
95
|
+
throw new CliError('Vault secret type must be "login" or "value"');
|
|
96
|
+
}
|
|
97
|
+
if (type === 'value') {
|
|
98
|
+
if (typeof value !== 'string') {
|
|
99
|
+
throw new CliError('Vault value secrets require --value, --value-from-file, or --input');
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
...common,
|
|
103
|
+
type: 'value',
|
|
104
|
+
value,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (typeof options.username !== 'string' || typeof password !== 'string') {
|
|
108
|
+
throw new CliError('Vault login secrets require --username and --password, --password-from-file, or --input');
|
|
109
|
+
}
|
|
73
110
|
return {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
111
|
+
...common,
|
|
112
|
+
type: 'login',
|
|
113
|
+
username: options.username,
|
|
114
|
+
password,
|
|
115
|
+
totpSecret: options.totpSecret,
|
|
116
|
+
};
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function createVaultPatchCommand(factory) {
|
|
121
|
+
return createJsonBodyCommand(factory, {
|
|
122
|
+
name: 'patch',
|
|
123
|
+
description: 'Update a vault secret',
|
|
124
|
+
method: 'patch',
|
|
125
|
+
path: '/vault/secrets/{key}',
|
|
126
|
+
argNames: ['key'],
|
|
127
|
+
configure: (cmd) => cmd
|
|
128
|
+
.option('--value <value>', 'Generic secret value')
|
|
129
|
+
.option('--value-from-file <path>', 'Read generic secret value from file, or - for stdin')
|
|
130
|
+
.option('--username <value>', 'Credential username')
|
|
131
|
+
.option('--password <value>', 'Credential password')
|
|
132
|
+
.option('--password-from-file <path>', 'Read password from file, or - for stdin')
|
|
133
|
+
.option('--totp-secret <secret>', 'TOTP seed')
|
|
134
|
+
.option('--clear-totp', 'Remove the TOTP seed')
|
|
135
|
+
.option('--label <label>', 'Display label')
|
|
136
|
+
.option('--clear-label', 'Remove the display label')
|
|
137
|
+
.option('--origin <origin...>', 'Allowed origin')
|
|
138
|
+
.option('--clear-origins', 'Remove origins')
|
|
139
|
+
.option('--origin-pattern <pattern...>', 'Allowed origin pattern')
|
|
140
|
+
.option('--clear-origin-patterns', 'Remove origin patterns')
|
|
141
|
+
.option('--input <path>', 'Read full JSON request body from file, or - for stdin'),
|
|
142
|
+
body: async (_args, options) => {
|
|
143
|
+
if (typeof options.input === 'string')
|
|
144
|
+
return readJsonFile(options.input);
|
|
145
|
+
const password = typeof options.passwordFromFile === 'string'
|
|
146
|
+
? (await readText(options.passwordFromFile)).trimEnd()
|
|
147
|
+
: options.password;
|
|
148
|
+
const value = typeof options.valueFromFile === 'string'
|
|
149
|
+
? (await readText(options.valueFromFile)).trimEnd()
|
|
150
|
+
: options.value;
|
|
151
|
+
const body = {
|
|
152
|
+
value,
|
|
153
|
+
username: options.username,
|
|
154
|
+
password,
|
|
155
|
+
totpSecret: options.clearTotp === true ? null : options.totpSecret,
|
|
156
|
+
label: options.clearLabel === true ? null : options.label,
|
|
157
|
+
origins: options.clearOrigins === true ? null : options.origin,
|
|
158
|
+
originPatterns: options.clearOriginPatterns === true ? null : options.originPattern,
|
|
85
159
|
};
|
|
160
|
+
if (!Object.values(body).some((value) => value !== undefined)) {
|
|
161
|
+
throw new CliError('Vault patch requires at least one field or --input');
|
|
162
|
+
}
|
|
163
|
+
return body;
|
|
86
164
|
},
|
|
87
165
|
});
|
|
88
166
|
}
|
|
89
167
|
function createVaultTotpCommand(factory) {
|
|
90
168
|
return addOutputFlags(new Command('totp')
|
|
91
169
|
.description('Generate the current TOTP code for a vault secret')
|
|
92
|
-
.argument('<
|
|
93
|
-
|
|
94
|
-
|
|
170
|
+
.argument('<key>')).action(async (key, options) => {
|
|
171
|
+
await requestAndPrint(factory, 'get', pathTemplate('/vault/secrets/{key}/totp', { key }), {
|
|
172
|
+
output: options,
|
|
173
|
+
});
|
|
95
174
|
});
|
|
96
175
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const StoredWhoamiSchema: z.ZodObject<{
|
|
3
|
-
authenticated: z.ZodLiteral<true>;
|
|
4
3
|
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
scope: z.ZodEnum<{
|
|
5
|
+
organization: "organization";
|
|
7
6
|
subaccount: "subaccount";
|
|
8
7
|
}>;
|
|
9
8
|
organizationId: z.ZodString;
|
|
10
|
-
subaccountId: z.
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
subaccountId: z.ZodNullable<z.ZodString>;
|
|
10
|
+
defaultSpaceId: z.ZodString;
|
|
11
|
+
keyId: z.ZodString;
|
|
13
12
|
plan: z.ZodString;
|
|
14
13
|
}, z.core.$strict>;
|
|
15
14
|
export type StoredWhoami = z.infer<typeof StoredWhoamiSchema>;
|
|
@@ -17,16 +16,15 @@ export declare const StoredAuthSchema: z.ZodObject<{
|
|
|
17
16
|
apiBaseUrl: z.ZodString;
|
|
18
17
|
token: z.ZodString;
|
|
19
18
|
whoami: z.ZodObject<{
|
|
20
|
-
authenticated: z.ZodLiteral<true>;
|
|
21
19
|
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
scope: z.ZodEnum<{
|
|
21
|
+
organization: "organization";
|
|
24
22
|
subaccount: "subaccount";
|
|
25
23
|
}>;
|
|
26
24
|
organizationId: z.ZodString;
|
|
27
|
-
subaccountId: z.
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
subaccountId: z.ZodNullable<z.ZodString>;
|
|
26
|
+
defaultSpaceId: z.ZodString;
|
|
27
|
+
keyId: z.ZodString;
|
|
30
28
|
plan: z.ZodString;
|
|
31
29
|
}, z.core.$strict>;
|
|
32
30
|
createdAt: z.ZodString;
|
|
@@ -5,13 +5,12 @@ import { z } from 'zod';
|
|
|
5
5
|
const DEFAULT_AUTH_FILE_NAME = 'auth.json';
|
|
6
6
|
export const StoredWhoamiSchema = z
|
|
7
7
|
.object({
|
|
8
|
-
authenticated: z.literal(true),
|
|
9
8
|
email: z.string().email().nullable().optional(),
|
|
10
|
-
|
|
9
|
+
scope: z.enum(['organization', 'subaccount']),
|
|
11
10
|
organizationId: z.string().min(1),
|
|
12
|
-
subaccountId: z.string().min(1).nullable()
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
subaccountId: z.string().min(1).nullable(),
|
|
12
|
+
defaultSpaceId: z.string().min(1),
|
|
13
|
+
keyId: z.string().min(1),
|
|
15
14
|
plan: z.string().min(1),
|
|
16
15
|
})
|
|
17
16
|
.strict();
|