Skip to content

Commit 9ea3bf2

Browse files
committed
Refactoring openapi-spec to work
1 parent fd39393 commit 9ea3bf2

File tree

854 files changed

+598
-379358
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

854 files changed

+598
-379358
lines changed

cmd/api.go

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cmd
22

33
import (
4-
"bytes"
54
"encoding/json"
65
"fmt"
76
"io"
@@ -13,7 +12,7 @@ import (
1312
"github.com/briandowns/spinner"
1413
"github.com/scalvert/glean-cli/pkg/config"
1514
"github.com/scalvert/glean-cli/pkg/http"
16-
"github.com/scalvert/glean-cli/pkg/jsoncolor"
15+
"github.com/scalvert/glean-cli/pkg/output"
1716
"github.com/spf13/cobra"
1817
"golang.org/x/term"
1918
)
@@ -139,22 +138,10 @@ func newApiCmd() *cobra.Command {
139138
return err
140139
}
141140

142-
if opts.raw || opts.noColor {
143-
// For raw or no-color output, pretty print without colors
144-
var prettyJSON bytes.Buffer
145-
if err := json.Indent(&prettyJSON, resp, "", " "); err != nil {
146-
return fmt.Errorf("failed to format JSON response: %w", err)
147-
}
148-
fmt.Println(prettyJSON.String())
149-
return nil
150-
}
151-
152-
// Use colorized JSON output
153-
if err := jsoncolor.Write(os.Stdout, bytes.NewReader(resp), " "); err != nil {
154-
return fmt.Errorf("failed to format JSON response: %w", err)
155-
}
156-
157-
return nil
141+
return output.Write(os.Stdout, resp, output.Options{
142+
NoColor: opts.raw || opts.noColor,
143+
Format: "json",
144+
})
158145
},
159146
}
160147

@@ -204,17 +191,10 @@ func previewRequest(req *http.Request, noColor bool) error {
204191
return fmt.Errorf("failed to format request body: %w", err)
205192
}
206193

207-
if noColor {
208-
var prettyJSON bytes.Buffer
209-
if err := json.Indent(&prettyJSON, bodyBytes, " ", " "); err != nil {
210-
return fmt.Errorf("failed to format request body: %w", err)
211-
}
212-
fmt.Println(prettyJSON.String())
213-
} else {
214-
if err := jsoncolor.Write(os.Stdout, bytes.NewReader(bodyBytes), " "); err != nil {
215-
return fmt.Errorf("failed to format request body: %w", err)
216-
}
217-
}
194+
return output.Write(os.Stdout, bodyBytes, output.Options{
195+
NoColor: noColor,
196+
Format: "json",
197+
})
218198
}
219199

220200
return nil

cmd/openapi_spec.go

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package cmd
22

33
import (
4-
"bufio"
54
"fmt"
5+
"io"
66
"os"
7-
"strings"
87

98
"github.com/MakeNowJust/heredoc"
109
"github.com/scalvert/glean-cli/pkg/llm"
10+
"github.com/scalvert/glean-cli/pkg/output"
1111
"github.com/spf13/cobra"
1212
)
1313

@@ -16,89 +16,89 @@ var (
1616
outputFile string
1717
prompt string
1818
model string
19+
noColor bool
1920
)
2021

21-
var openapiSpecCmd = &cobra.Command{
22-
Use: "openapi-spec",
23-
Short: "Generate an OpenAPI spec from an API definition or curl command",
24-
Long: heredoc.Doc(`
25-
This command reads an input (either stdin or a file) describing an API endpoint or
26-
a curl command and generates an OpenAPI spec, simplifying the creation of Glean Actions.
27-
28-
Usage:
29-
# Generate from a file
30-
glean generate openapi-spec -f input.txt -o spec.yaml
31-
32-
# Generate from stdin
33-
echo "curl example.com/api" | glean generate openapi-spec
34-
35-
# Add custom instructions
36-
glean generate openapi-spec -f input.txt --prompt "Include rate limiting details"
37-
38-
Input Format:
39-
- A curl command
40-
- An API description in a simple format
41-
42-
Output:
43-
OpenAPI specification in YAML format
44-
`),
45-
SilenceUsage: true,
46-
SilenceErrors: true,
47-
RunE: func(cmd *cobra.Command, args []string) error {
48-
var input string
49-
50-
if inputFile != "" {
51-
data, err := os.ReadFile(inputFile)
52-
53-
if err != nil {
54-
return fmt.Errorf("could not read file: %w", err)
22+
func newOpenapiSpecCmd() *cobra.Command {
23+
cmd := &cobra.Command{
24+
Use: "openapi-spec",
25+
Short: "Generate an OpenAPI spec from an API definition or curl command",
26+
Long: heredoc.Doc(`
27+
Generate an OpenAPI specification from an API definition or curl command.
28+
29+
The input can be provided via a file or through stdin:
30+
glean generate openapi-spec -f api.txt
31+
echo "curl example.com/api" | glean generate openapi-spec
32+
33+
The generated spec will be in YAML format and can be saved to a file:
34+
glean generate openapi-spec -f api.txt -o spec.yaml
35+
36+
Add custom instructions to guide the generation:
37+
glean generate openapi-spec -f api.txt --prompt "Include rate limiting details"
38+
39+
Use --no-color to disable colorized output.
40+
`),
41+
Example: heredoc.Doc(`
42+
# Generate from a curl command
43+
$ echo 'curl -X POST https://api.example.com/users \
44+
-H "Content-Type: application/json" \
45+
-d '"'"'{"name": "John", "email": "john@example.com"}'"'"'' | \
46+
glean generate openapi-spec
47+
48+
# Generate from a file with custom instructions
49+
$ glean generate openapi-spec -f api.txt --prompt "Include authentication details"
50+
51+
# Save to a file
52+
$ glean generate openapi-spec -f api.txt -o spec.yaml
53+
`),
54+
RunE: func(cmd *cobra.Command, args []string) error {
55+
var input []byte
56+
var err error
57+
58+
if inputFile == "-" || inputFile == "" {
59+
input, err = io.ReadAll(os.Stdin)
60+
if err != nil {
61+
return fmt.Errorf("failed to read from stdin: %w", err)
62+
}
63+
if len(input) == 0 {
64+
return fmt.Errorf("no input provided")
65+
}
66+
} else {
67+
input, err = os.ReadFile(inputFile)
68+
if err != nil {
69+
return fmt.Errorf("failed to read input file: %w", err)
70+
}
5571
}
56-
input = string(data)
57-
} else {
58-
stat, _ := os.Stdin.Stat()
5972

60-
if (stat.Mode() & os.ModeCharDevice) != 0 {
61-
return fmt.Errorf("no input found; please provide a file or pipe input to stdin")
62-
}
63-
64-
scanner := bufio.NewScanner(os.Stdin)
65-
66-
var lines []string
67-
68-
for scanner.Scan() {
69-
lines = append(lines, scanner.Text())
73+
spec, err := llm.GenerateOpenAPISpec(string(input), prompt, model)
74+
if err != nil {
75+
return fmt.Errorf("failed to generate OpenAPI spec: %w", err)
7076
}
7177

72-
if err := scanner.Err(); err != nil {
73-
return fmt.Errorf("error reading input: %w", err)
78+
if outputFile != "" {
79+
if err := os.WriteFile(outputFile, []byte(spec), 0644); err != nil {
80+
return fmt.Errorf("failed to write output file: %w", err)
81+
}
82+
fmt.Fprintf(cmd.OutOrStdout(), "OpenAPI spec written to %s\n", outputFile)
83+
return nil
7484
}
7585

76-
input = strings.Join(lines, "\n")
77-
}
78-
79-
spec, err := llm.GenerateOpenAPISpec(input, prompt, model)
80-
if err != nil {
81-
return err
82-
}
86+
return output.WriteString(cmd.OutOrStdout(), spec, output.Options{
87+
NoColor: noColor,
88+
Format: "yaml",
89+
})
90+
},
91+
}
8392

84-
if outputFile != "" {
85-
if err := os.WriteFile(outputFile, []byte(spec), 0600); err != nil {
86-
return fmt.Errorf("failed to write output file: %w", err)
87-
}
88-
fmt.Printf("OpenAPI spec written to %s\n", outputFile)
89-
} else {
90-
fmt.Println(spec)
91-
}
93+
cmd.Flags().StringVarP(&inputFile, "file", "f", "", "Input file containing the API/curl command (use \"-\" for stdin)")
94+
cmd.Flags().StringVarP(&outputFile, "output", "o", "", "Output file for the OpenAPI spec")
95+
cmd.Flags().StringVarP(&prompt, "prompt", "p", "", "Additional instructions for the LLM")
96+
cmd.Flags().StringVar(&model, "model", "gpt-4", "LLM model to use")
97+
cmd.Flags().BoolVar(&noColor, "no-color", false, "Disable colorized output")
9298

93-
return nil
94-
},
99+
return cmd
95100
}
96101

97102
func init() {
98-
generateCmd.AddCommand(openapiSpecCmd)
99-
100-
openapiSpecCmd.Flags().StringVarP(&inputFile, "file", "f", "", "Input file containing the API/curl command")
101-
openapiSpecCmd.Flags().StringVarP(&outputFile, "output", "o", "", "Output file for the OpenAPI spec (defaults to stdout)")
102-
openapiSpecCmd.Flags().StringVarP(&prompt, "prompt", "p", "", "Additional instructions for the LLM")
103-
openapiSpecCmd.Flags().StringVar(&model, "model", "gpt-4", "LLM model to use")
103+
generateCmd.AddCommand(newOpenapiSpecCmd())
104104
}

0 commit comments

Comments
 (0)