Skip to content

Commit 20c8403

Browse files
committed
feat: export fctl commands as json
1 parent 7b7cb45 commit 20c8403

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

tools/commandusage/export.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
8+
"github.com/formancehq/fctl/cmd"
9+
"github.com/spf13/cobra"
10+
"github.com/spf13/pflag"
11+
)
12+
13+
var (
14+
file = "inventory.json"
15+
)
16+
17+
type Flag struct {
18+
Name string `json:"name"`
19+
Description string `json:"description"`
20+
Deprecated string `json:"deprecated,omitempty"`
21+
Usage string `json:"usage"`
22+
DefaultValue string `json:"default_value,omitempty"`
23+
Type string `json:"type,omitempty"`
24+
}
25+
26+
type DocCommand struct {
27+
Name string `json:"name"`
28+
Usage string `json:"usage"`
29+
Description string `json:"description"`
30+
Deprecated string `json:"deprecated,omitempty"`
31+
Aliases []string `json:"aliases,omitempty"`
32+
33+
Flags []Flag `json:"flags,omitempty"`
34+
GlobalFlags []Flag `json:"global_flags,omitempty"`
35+
36+
SubCommands []DocCommand `json:"subcommands,omitempty"`
37+
}
38+
39+
func flagSetToFlags(flagSet *pflag.FlagSet) []Flag {
40+
flags := make([]Flag, 0)
41+
42+
flagSet.VisitAll(func(f *pflag.Flag) {
43+
if f.Hidden {
44+
return
45+
}
46+
flags = append(flags, Flag{
47+
Name: f.Name,
48+
Description: f.Usage,
49+
Deprecated: f.Deprecated,
50+
DefaultValue: f.DefValue,
51+
Usage: f.Usage,
52+
Type: f.Value.Type(),
53+
})
54+
})
55+
56+
return flags
57+
}
58+
59+
func writeDocs(parentCommandName string, command *cobra.Command, file *os.File) {
60+
flags := flagSetToFlags(command.Flags())
61+
globalFlags := flagSetToFlags(command.Root().PersistentFlags())
62+
63+
doc := DocCommand{
64+
Name: func() string {
65+
if parentCommandName != "" {
66+
return fmt.Sprintf("%s %s", parentCommandName, command.Name())
67+
}
68+
return command.Name()
69+
}(),
70+
Usage: command.Use,
71+
Description: command.Short,
72+
Deprecated: command.Deprecated,
73+
Aliases: command.Aliases,
74+
Flags: flags,
75+
GlobalFlags: globalFlags,
76+
}
77+
78+
docAsJson, err := json.Marshal(&doc)
79+
if err != nil {
80+
panic(err)
81+
}
82+
83+
if _, err := file.Write(docAsJson); err != nil {
84+
panic(err)
85+
}
86+
}
87+
88+
func visitSubCommands(command *cobra.Command, file *os.File) {
89+
var (
90+
parentCommand *cobra.Command
91+
parentName string
92+
)
93+
94+
if command != command.Root() {
95+
parentCommand = command.Parent()
96+
parentName = parentCommand.Name()
97+
}
98+
99+
label:
100+
if command.HasParent() && command.Parent() != command.Root() {
101+
parentCommand = parentCommand.Parent()
102+
if parentCommand != nil {
103+
parentName = parentCommand.Name() + " " + parentName
104+
goto label
105+
}
106+
}
107+
108+
writeDocs(parentName, command, file)
109+
for _, subCommand := range command.Commands() {
110+
writeDocs(parentName, subCommand, file)
111+
visitSubCommands(subCommand, file)
112+
}
113+
}
114+
115+
//go:generate rm -rf docs
116+
//go:generate go run ./
117+
func main() {
118+
_, err := os.Stat(file)
119+
if os.IsNotExist(err) {
120+
if err := os.WriteFile(file, []byte("[]"), 0644); err != nil {
121+
panic(err)
122+
}
123+
} else {
124+
os.Remove(file)
125+
}
126+
127+
file, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
128+
if err != nil {
129+
panic(err)
130+
}
131+
defer file.Close()
132+
133+
visitSubCommands(cmd.NewRootCommand(), file)
134+
}

tools/commandusage/inventory.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)