Skip to content

Commit 994a967

Browse files
committed
improvement(cli): sim credentials providers lists providers
1 parent e985d51 commit 994a967

4 files changed

Lines changed: 42 additions & 3 deletions

File tree

‎packages/sim-cli/src/contract/commands.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,10 @@ export const CLI_CONTRACT: CliContract = {
14611461
// `serviceId`, while `credentials create` matches a service-account provider
14621462
// on `providerId`. Each is empty on the kind of row that does not use it.
14631463
listCredentialProviders: {
1464+
// The providers group holds nothing but this list, so naming the group lists them.
1465+
command: 'credentials providers',
1466+
groupDefault: true,
1467+
variants: [{ command: 'credentials providers list' }],
14641468
columns: [
14651469
{ header: 'type' },
14661470
{ header: 'service', path: 'serviceId' },

‎packages/sim-cli/src/contract/types.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export interface CommandSpec {
248248
* `<resource> [sub-resource] <verb>` name.
249249
*/
250250
command?: string
251-
/** Run this operation when its top-level group is invoked without a subcommand. */
251+
/** Run this operation when its group (`command`, top-level or nested) is invoked without a subcommand. */
252252
groupDefault?: boolean
253253
/** Alternate leaf command names, such as `ls` for `list`. */
254254
aliases?: readonly string[]

‎packages/sim-cli/src/runtime/build.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,10 @@ export function buildGeneratedCommands(): Command[] {
498498
const segments = spec.command ? spec.command.split(' ') : deriveCommandPath(operation)
499499
if (spec.groupDefault) {
500500
const [groupName, ...rest] = segments
501-
const group = groupFor(groups, groupName)
502-
if (rest.length > 0) throw new Error(`${operation} groupDefault must name a command group`)
501+
const group = rest.reduce(
502+
(parent, segment) => nestedGroup(parent, segment),
503+
groupFor(groups, groupName)
504+
)
503505
const pathPositionals = operationSpec.pathParams.filter(
504506
(param) => !spec.pathFlags?.[param] && !isProfileWorkspacePath(spec, param)
505507
)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { runEmbeddedCli } from '../embed'
3+
4+
const identity = { endpoint: 'https://sim.test', apiKey: 'fixture', workspaceId: 'workspace' }
5+
6+
/** Runs one embedded invocation, recording the path of each request it sends. */
7+
async function run(argv: string[]) {
8+
const paths: string[] = []
9+
const result = await runEmbeddedCli(argv, {
10+
...identity,
11+
transport: async (url) => {
12+
paths.push(new URL(String(url)).pathname)
13+
return Response.json({ data: [] })
14+
},
15+
})
16+
return { ...result, paths }
17+
}
18+
19+
describe('a nested group that defaults to its list', () => {
20+
it('lists credential providers when the providers group is named, as list does', async () => {
21+
const bare = await run(['credentials', 'providers'])
22+
const listed = await run(['credentials', 'providers', 'list'])
23+
expect(bare.exitCode).toBe(0)
24+
expect(bare.paths).toEqual(['/api/v2/credentials/providers'])
25+
expect(listed.paths).toEqual(bare.paths)
26+
})
27+
28+
it('leaves a group without a default printing its usage, sending nothing', async () => {
29+
const group = await run(['credentials'])
30+
expect(group.paths).toEqual([])
31+
expect(group.stderr + group.stdout).toContain('Usage: sim credentials')
32+
})
33+
})

0 commit comments

Comments
 (0)