-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathcommand-preview.ts
More file actions
95 lines (83 loc) · 2.59 KB
/
Copy pathcommand-preview.ts
File metadata and controls
95 lines (83 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
export type CommandClassification = {
readOnly: boolean
destructive: boolean
idempotent: boolean
}
/**
* The subset of oclif's parse metadata we rely on: which flags were filled in from
* `default:` rather than typed by the user. Pass `metadata.flags` from `this.parse()`.
*/
export type FlagMetadata = Record<string, { setFromDefault?: boolean } | undefined>
export type CommandPreview = {
command: string
description: string
changes: string[]
flags: Record<string, unknown>
flagMetadata?: FlagMetadata
args?: Record<string, unknown>
classification: CommandClassification
}
export type AgentPreviewResponse = {
status: 'confirmation_required' | 'dry_run'
command: string
description: string
classification: CommandClassification
changes: string[]
confirmCommand: string
}
const OMITTED_FLAGS: ReadonlySet<string> = new Set(['output', 'force', 'dry-run'])
export function buildConfirmCommand (
command: string,
flags: Record<string, unknown>,
args?: Record<string, unknown>,
flagMetadata?: FlagMetadata,
): string {
const parts = ['checkly', command]
if (args) {
for (const value of Object.values(args)) {
parts.push(String(value))
}
}
for (const [key, value] of Object.entries(flags)) {
if (OMITTED_FLAGS.has(key)) continue
if (value === undefined || value === null) continue
// Defaults are not part of what the user asked for, and a default `false` renders as
// `--no-x`, which only parses when the flag sets `allowNo: true`.
if (flagMetadata?.[key]?.setFromDefault) continue
if (Array.isArray(value)) {
for (const item of value) {
parts.push(`--${key}="${item}"`)
}
} else if (typeof value === 'boolean') {
parts.push(value ? `--${key}` : `--no-${key}`)
} else {
parts.push(`--${key}="${value}"`)
}
}
parts.push('--force')
return parts.join(' ')
}
export function formatPreviewForAgent (
preview: CommandPreview,
status: 'confirmation_required' | 'dry_run',
): AgentPreviewResponse {
return {
status,
command: preview.command,
description: preview.description,
classification: preview.classification,
changes: preview.changes,
confirmCommand: buildConfirmCommand(preview.command, preview.flags, preview.args, preview.flagMetadata),
}
}
export function formatPreviewForTerminal (preview: CommandPreview): string {
if (preview.changes.length === 1) {
return `This will ${preview.changes[0]}`
}
const lines: string[] = []
lines.push('This will:')
for (const change of preview.changes) {
lines.push(` - ${change}`)
}
return lines.join('\n')
}