Expand generated code, add routes list
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
package get
|
||||
|
||||
import (
|
||||
"github.com/k0kubun/pp/v3"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"gitea.libretechconsulting.com/50W/eia-api-go/cmd/eia-client/internal/util"
|
||||
@ -15,4 +16,12 @@ var GetFacetsCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func RunGetFacetCmd(cmd *cobra.Command, args []string) {
|
||||
logger := util.Logger(cmd)
|
||||
|
||||
facet, err := util.GetFacet(cmd, args[0], args[1])
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Send()
|
||||
}
|
||||
|
||||
pp.Println(facet)
|
||||
}
|
||||
|
@ -9,5 +9,6 @@ var ListCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
ListCmd.AddCommand(ListFacetsCmd)
|
||||
ListCmd.AddCommand(listFacetsCmd)
|
||||
ListCmd.AddCommand(listRoutesCmd)
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"gitea.libretechconsulting.com/50W/eia-api-go/cmd/eia-client/internal/util"
|
||||
)
|
||||
|
||||
var ListFacetsCmd = &cobra.Command{
|
||||
var listFacetsCmd = &cobra.Command{
|
||||
Use: "facets route",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "List facets for given API route",
|
||||
|
79
cmd/eia-client/cmd/list/list_routes.go
Normal file
79
cmd/eia-client/cmd/list/list_routes.go
Normal file
@ -0,0 +1,79 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/k0kubun/pp/v3"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"gitea.libretechconsulting.com/50W/eia-api-go/cmd/eia-client/internal/util"
|
||||
"gitea.libretechconsulting.com/50W/eia-api-go/pkg/eia"
|
||||
)
|
||||
|
||||
var listRoutesCmd = &cobra.Command{
|
||||
Use: "routes",
|
||||
Aliases: []string{"methods", "r"},
|
||||
Short: "List routes, optionally by type (default is Data)",
|
||||
Args: cobra.MaximumNArgs(2),
|
||||
ValidArgs: []string{
|
||||
"Data",
|
||||
"Facet",
|
||||
},
|
||||
Run: RunListRoutesCmd,
|
||||
}
|
||||
|
||||
const (
|
||||
allMethodsFlag = "all"
|
||||
filtersFlag = "filters"
|
||||
routePrefixFlag = "routePrefix"
|
||||
)
|
||||
|
||||
func RunListRoutesCmd(cmd *cobra.Command, args []string) {
|
||||
logger := util.Logger(cmd)
|
||||
|
||||
// Command flags
|
||||
allRoutes, _ := cmd.Flags().GetBool(allMethodsFlag)
|
||||
routePrefix, _ := cmd.Flags().GetString(routePrefixFlag)
|
||||
filters, _ := cmd.Flags().GetStringSlice(filtersFlag)
|
||||
|
||||
if allRoutes && len(args) > 0 {
|
||||
logger.Fatal().Msg("can't specify all methods while also filtering by type")
|
||||
}
|
||||
|
||||
filter := make([]string, 0)
|
||||
if !allRoutes && len(args) == 1 {
|
||||
filter = append(filter, args[0])
|
||||
} else if !allRoutes {
|
||||
filter = append(filter, "Data")
|
||||
}
|
||||
|
||||
routes := eia.GetRoutes(filter...)
|
||||
filteredRoutes := make([]string, 0, len(routes))
|
||||
|
||||
// Apply filters for routePrefix, and optional filters
|
||||
for _, route := range routes {
|
||||
if !allRoutes && routePrefix != "" {
|
||||
if !strings.HasPrefix(strings.ToLower(route), strings.ToLower(routePrefix)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(filters) > 0 {
|
||||
for _, f := range filters {
|
||||
if strings.Contains(strings.ToLower(route), strings.ToLower(f)) {
|
||||
filteredRoutes = append(filteredRoutes, route)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filteredRoutes = append(filteredRoutes, route)
|
||||
}
|
||||
}
|
||||
|
||||
pp.Println(filteredRoutes)
|
||||
}
|
||||
|
||||
func init() {
|
||||
listRoutesCmd.PersistentFlags().BoolP(allMethodsFlag, "a", false, "List all methods, no filtering")
|
||||
listRoutesCmd.PersistentFlags().StringSliceP(filtersFlag, "f", []string{}, "Optional filters, case insensitive")
|
||||
listRoutesCmd.PersistentFlags().StringP(routePrefixFlag, "p", "Get", "Prefix for routes, ignore with -a flag")
|
||||
}
|
@ -89,8 +89,8 @@ func init() {
|
||||
rootCmd.PersistentFlags().StringP(util.FLAG_API_LOG_LEVEL, "L", "",
|
||||
"Log Level for EIA API Middleware, or set "+util.ENV_API_LOG_LEVEL+" in environment")
|
||||
|
||||
rootCmd.PersistentFlags().StringP(util.FLAG_APIKEY,
|
||||
"a", "", "API Key, or set "+util.ENV_API+" in environment")
|
||||
rootCmd.PersistentFlags().String(util.FLAG_APIKEY,
|
||||
"", "API Key, or set "+util.ENV_API+" in environment")
|
||||
|
||||
rootCmd.PersistentFlags().DurationP(util.FLAG_TMOUT, "t", util.DefRequestTimeout,
|
||||
"Request timeout, or set "+util.ENV_TMOUT+" in environment")
|
||||
|
@ -39,7 +39,7 @@ func CompleteFacet(cmd *cobra.Command, args []string, toComplete string) ([]stri
|
||||
}
|
||||
|
||||
func CompleteRoute(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
routes := eia.GetRoutes()
|
||||
routes := eia.GetRoutes("Facet")
|
||||
compRoutes := make([]string, 0, len(routes))
|
||||
|
||||
for _, r := range routes {
|
||||
|
@ -1,177 +1,26 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
eiaapi "gitea.libretechconsulting.com/50W/eia-api-go/api"
|
||||
"gitea.libretechconsulting.com/50W/eia-api-go/pkg/eia"
|
||||
)
|
||||
|
||||
type MethodSubs struct {
|
||||
TypedParams map[reflect.Type]reflect.Value // Replace field of specific type with value
|
||||
NameParams map[string]reflect.Value // Replace field with specific name with value
|
||||
NameContainsParams map[string]reflect.Value // Replace fields with name containing string with value
|
||||
}
|
||||
func GetFacet(cmd *cobra.Command, route string, facet string) (*eiaapi.FacetDetails, error) {
|
||||
client, err := Client(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var defaultMethodSubs = MethodSubs{
|
||||
NameContainsParams: map[string]reflect.Value{
|
||||
"route": reflect.ValueOf(strconv.Itoa(time.Now().AddDate(-1, 0, 0).Year())),
|
||||
},
|
||||
return client.GetFacet(cmd.Context(), route, facet, eia.DefaultMethodSubs(cmd.Context()))
|
||||
}
|
||||
|
||||
// func GetFacet(cmd *cobra.Command, route string) (*eiaapi.FacetOptionList, error) {
|
||||
// }
|
||||
|
||||
func GetFacets(cmd *cobra.Command, route string) (*eiaapi.FacetOptionList, error) {
|
||||
client, err := Client(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the reflect.Value of the target object
|
||||
targetValue := reflect.ValueOf(client)
|
||||
|
||||
// Get the method by name
|
||||
method := targetValue.MethodByName(route)
|
||||
if !method.IsValid() {
|
||||
return nil, fmt.Errorf("method %q not found", route)
|
||||
}
|
||||
|
||||
args := prepMethodArgs(cmd.Context(), method, GetMethodSubs(cmd))
|
||||
|
||||
// Prepare a parser func for our facet response
|
||||
parserFunc, exists := eiaapi.ParseFunctionsMap[fmt.Sprintf("Parse%sResponse", route)]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("parser func for %s not found", route)
|
||||
}
|
||||
|
||||
parser := reflect.ValueOf(parserFunc)
|
||||
if !parser.IsValid() {
|
||||
return nil, errors.New("unable to find parser for facet response")
|
||||
}
|
||||
|
||||
// Perform the API call
|
||||
results := method.Call(args)
|
||||
if len(results) != 2 {
|
||||
return nil, errors.New("unexpected response from get facet call")
|
||||
}
|
||||
|
||||
// Prepare *http.Response, error
|
||||
resp, err := getResponse(results)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Call the parser with our response, then extract the JSON200 response,
|
||||
// and return the expected FacetOptiionsList from the container
|
||||
|
||||
results = parser.Call([]reflect.Value{reflect.ValueOf(resp)})
|
||||
if len(results) != 2 {
|
||||
return nil, errors.New("unexpected response while parsing facet response")
|
||||
}
|
||||
if err := checkCallErr(results[1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := results[0]
|
||||
if result.Kind() == reflect.Ptr {
|
||||
result = result.Elem()
|
||||
}
|
||||
|
||||
if result.Kind() != reflect.Struct {
|
||||
return nil, fmt.Errorf("unexpected parse result kind %s", result.Kind().String())
|
||||
}
|
||||
|
||||
field := result.FieldByName("JSON200")
|
||||
if !field.IsValid() {
|
||||
return nil, errors.New("invalid facet data field in response")
|
||||
}
|
||||
|
||||
facetOptions, ok := field.Interface().(*eiaapi.FacetOptionListContainer)
|
||||
if !ok {
|
||||
return nil, errors.New("response does not contain facet options")
|
||||
}
|
||||
|
||||
if facetOptions == nil {
|
||||
return nil, errors.New("no facet options found for facet request")
|
||||
}
|
||||
|
||||
return facetOptions.Response, nil
|
||||
}
|
||||
|
||||
// Given an API method, replaces any named fields with the provided value
|
||||
// from the subs map, otherwise uses built-in logic for common fields
|
||||
// such as a context.Context. Skips request editor funcs
|
||||
func prepMethodArgs(ctx context.Context, method reflect.Value, _ MethodSubs) []reflect.Value {
|
||||
// Create a slice of reflect.Value for the method's arguments
|
||||
methodType := method.Type()
|
||||
args := make([]reflect.Value, 0, methodType.NumIn())
|
||||
|
||||
// Populate arguments with zero values for their respective types
|
||||
for i := 0; i < methodType.NumIn(); i++ {
|
||||
argType := methodType.In(i)
|
||||
|
||||
// Don't supply request editor Fn args
|
||||
if methodType.IsVariadic() && i == methodType.NumIn()-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if argType == reflect.TypeOf((*context.Context)(nil)).Elem() {
|
||||
args = append(args, reflect.ValueOf(ctx))
|
||||
continue
|
||||
}
|
||||
|
||||
// Default to last year for Route1
|
||||
if argType == reflect.TypeOf(eiaapi.Route1("1999")) {
|
||||
lastYear := time.Now().AddDate(-1, 0, 0).Year()
|
||||
args = append(args, reflect.ValueOf(eiaapi.Route1(strconv.Itoa(lastYear))))
|
||||
continue
|
||||
}
|
||||
|
||||
// Zero value of other stuff
|
||||
args = append(args, reflect.Zero(argType))
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
func getResponse(responses []reflect.Value) (*http.Response, error) {
|
||||
resp, ok := responses[0].Interface().(*http.Response)
|
||||
if !ok {
|
||||
return nil, errors.New("no or invalid response received from call")
|
||||
}
|
||||
|
||||
if err := checkCallErr(responses[1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func checkCallErr(val reflect.Value) error {
|
||||
var err error
|
||||
var ok bool
|
||||
|
||||
if val.IsValid() && !val.IsNil() {
|
||||
if err, ok = val.Interface().(error); !ok {
|
||||
return errors.New("unexpected call response")
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func GetMethodSubs(cmd *cobra.Command) MethodSubs {
|
||||
subs := defaultMethodSubs
|
||||
|
||||
subs.TypedParams[reflect.TypeOf(context.Background())] = reflect.ValueOf(cmd.Context())
|
||||
|
||||
return subs
|
||||
return client.GetFacets(cmd.Context(), route, eia.DefaultMethodSubs(cmd.Context()))
|
||||
}
|
||||
|
Reference in New Issue
Block a user