-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
bundle.go
153 lines (130 loc) · 4.49 KB
/
bundle.go
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2023-2024 Princess Beef Heavy Industries, LLC / Dave Shanley
// https://pb33f.io
// Copyright 2022 Dave Shanley / Quobix
// SPDX-License-Identifier: MIT
package cmd
import (
"bytes"
"errors"
"fmt"
"log/slog"
"os"
"github.com/pb33f/libopenapi/bundler"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
)
func GetBundleCommand() *cobra.Command {
cmd := &cobra.Command{
SilenceUsage: true,
Use: "bundle",
Short: "Bundle an OpenAPI specification with external references into a single document.",
Long: "Bundle an OpenAPI specification with external references into a single document. All references will be resolved and " +
"the resulting document will be a valid OpenAPI specification, containing no references. It can then be used by any tool that does not support references.",
Example: "vacuum bundle <my-exploded-openapi-spec.yaml> <bundled-openapi-spec.yaml>",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return []string{"yaml", "yml", "json"}, cobra.ShellCompDirectiveFilterFileExt
}
return nil, cobra.ShellCompDirectiveNoFileComp
},
RunE: func(cmd *cobra.Command, args []string) error {
stdIn, _ := cmd.Flags().GetBool("stdin")
stdOut, _ := cmd.Flags().GetBool("stdout")
noStyleFlag, _ := cmd.Flags().GetBool("no-style")
baseFlag, _ := cmd.Flags().GetString("base")
remoteFlag, _ := cmd.Flags().GetBool("remote")
// disable color and styling, for CI/CD use.
// https://github.com/daveshanley/vacuum/issues/234
if noStyleFlag {
pterm.DisableColor()
pterm.DisableStyling()
}
if !stdIn && !stdOut {
PrintBanner()
}
if !stdIn && len(args) == 0 {
errText := "please supply input (unbundled) OpenAPI document, or use the -i flag to use stdin"
pterm.Error.Println(errText)
pterm.Println()
pterm.Println("Usage: vacuum bundle <input-openapi-spec.yaml> <output-bundled-openapi-spec.yaml>")
pterm.Println()
return errors.New(errText)
}
// check for file args
if !stdOut && len(args) == 1 {
errText := "please supply output (bundled) OpenAPI document, or use the -o flag to use stdout"
pterm.Error.Println(errText)
pterm.Println()
pterm.Println("Usage: vacuum bundle <input-openapi-spec.yaml> <output-bundled-openapi-spec.yaml>")
pterm.Println()
return errors.New(errText)
}
var specBytes []byte
var fileError error
if stdIn {
// read file from stdin
inputReader := cmd.InOrStdin()
buf := &bytes.Buffer{}
_, fileError = buf.ReadFrom(inputReader)
specBytes = buf.Bytes()
} else {
// read file from filesystem
specBytes, fileError = os.ReadFile(args[0])
}
if fileError != nil {
pterm.Error.Printf("Unable to read file '%s': %s\n", args[0], fileError.Error())
pterm.Println()
return fileError
}
if baseFlag == "" {
baseFlag = "."
}
// setup logging
handler := pterm.NewSlogHandler(&pterm.Logger{
Formatter: pterm.LogFormatterColorful,
Writer: os.Stdout,
Level: pterm.LogLevelWarn,
ShowTime: false,
MaxWidth: 280,
KeyStyles: map[string]pterm.Style{
"error": *pterm.NewStyle(pterm.FgRed, pterm.Bold),
"err": *pterm.NewStyle(pterm.FgRed, pterm.Bold),
"caller": *pterm.NewStyle(pterm.FgGray, pterm.Bold),
},
})
logger := slog.New(handler)
docConfig := &datamodel.DocumentConfiguration{
BasePath: baseFlag,
ExtractRefsSequentially: true,
Logger: logger,
AllowRemoteReferences: remoteFlag,
}
bundled, err := bundler.BundleBytes(specBytes, docConfig)
if err != nil {
pterm.Error.Printf("Bundling had errors: %s\n", err.Error())
pterm.Println()
if bundled == nil {
return err
}
}
if stdOut {
fmt.Print(string(bundled))
return nil
}
err = os.WriteFile(args[1], bundled, 0664)
if err != nil {
pterm.Error.Printf("Unable to write bundled file: '%s': %s\n", args[1], err.Error())
pterm.Println()
return err
}
pterm.Success.Printf("Bundled OpenAPI document written to '%s'\n", args[1])
pterm.Println()
return nil
},
}
cmd.Flags().BoolP("stdin", "i", false, "Use stdin as input, instead of a file")
cmd.Flags().BoolP("stdout", "o", false, "Use stdout as output, instead of a file")
cmd.Flags().BoolP("no-style", "q", false, "Disable styling and color output, just plain text (useful for CI/CD)")
return cmd
}