Skip to content

Commit 3570ba6

Browse files
committed
feat: export fctl commands as json
1 parent 7b7cb45 commit 3570ba6

File tree

3 files changed

+133
-1
lines changed

3 files changed

+133
-1
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require (
1717
github.com/pterm/pterm v0.12.81
1818
github.com/segmentio/ksuid v1.0.4
1919
github.com/spf13/cobra v1.8.1
20+
github.com/spf13/pflag v1.0.5
2021
github.com/zitadel/oidc/v2 v2.12.2
2122
golang.org/x/mod v0.25.0
2223
golang.org/x/oauth2 v0.30.0
@@ -61,7 +62,6 @@ require (
6162
github.com/rivo/uniseg v0.4.7 // indirect
6263
github.com/sergi/go-diff v1.3.1 // indirect
6364
github.com/sirupsen/logrus v1.9.3 // indirect
64-
github.com/spf13/pflag v1.0.5 // indirect
6565
github.com/stretchr/testify v1.9.0 // indirect
6666
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
6767
github.com/uptrace/bun v1.2.3 // indirect

tools/commandusage/export.go

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

tools/commandusage/inventory.json

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

0 commit comments

Comments
 (0)