Implement get route subcommand
This commit is contained in:
parent
5d2d247dde
commit
521e376455
@ -1,20 +1,26 @@
|
|||||||
package get
|
package get
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/k0kubun/pp/v3"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"gitea.libretechconsulting.com/50W/eia-api-go/cmd/eia-client/internal/util"
|
"gitea.libretechconsulting.com/50W/eia-api-go/cmd/eia-client/internal/util"
|
||||||
"gitea.libretechconsulting.com/50W/eia-api-go/pkg/eia"
|
"gitea.libretechconsulting.com/50W/eia-api-go/pkg/eia"
|
||||||
)
|
)
|
||||||
|
|
||||||
var filteredSuffixes = []string{
|
var (
|
||||||
"Data",
|
filteredSuffixes = []string{
|
||||||
"Facet",
|
"Facet",
|
||||||
"FacetId",
|
"FacetId",
|
||||||
"Body",
|
"Body",
|
||||||
}
|
}
|
||||||
|
filteredPrefixes = []string{
|
||||||
|
"EIAA",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
var GetRouteCmd = &cobra.Command{
|
var GetRouteCmd = &cobra.Command{
|
||||||
Use: "route",
|
Use: "route",
|
||||||
@ -28,24 +34,46 @@ var GetRouteCmd = &cobra.Command{
|
|||||||
func RunGetRouteCmd(cmd *cobra.Command, args []string) {
|
func RunGetRouteCmd(cmd *cobra.Command, args []string) {
|
||||||
logger := util.Logger(cmd)
|
logger := util.Logger(cmd)
|
||||||
logger.Info().Str("route", args[0]).Msg("getting route description")
|
logger.Info().Str("route", args[0]).Msg("getting route description")
|
||||||
|
|
||||||
|
route, err := util.GetRoute(cmd, args[0])
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal().Err(err).Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
pp.Println(route)
|
||||||
}
|
}
|
||||||
|
|
||||||
func completeRouteRoutes(cmd *cobra.Command, args []string, toComplete string) (
|
func completeRouteRoutes(cmd *cobra.Command, args []string, toComplete string) (
|
||||||
[]string, cobra.ShellCompDirective,
|
[]string, cobra.ShellCompDirective,
|
||||||
) {
|
) {
|
||||||
routes := eia.GetRoutes()
|
routes := eia.GetRoutes("Data")
|
||||||
routeRoutes := make([]string, 0, len(routes))
|
routeRoutes := make([]string, 0, len(routes))
|
||||||
for _, r := range routes {
|
for _, r := range routes {
|
||||||
|
var rName string
|
||||||
for _, suffix := range filteredSuffixes {
|
for _, suffix := range filteredSuffixes {
|
||||||
if strings.HasSuffix(r, suffix) {
|
if strings.HasSuffix(r, suffix) {
|
||||||
goto next
|
goto next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
routeRoutes = append(routeRoutes, r)
|
for _, prefix := range filteredPrefixes {
|
||||||
|
if strings.HasPrefix(r, prefix) {
|
||||||
|
goto next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rName, _ = strings.CutSuffix(r, "Data")
|
||||||
|
routeRoutes = append(routeRoutes, rName)
|
||||||
next:
|
next:
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Filter for toComplete
|
filteredRoutes := make([]string, 0, len(routeRoutes))
|
||||||
|
if toComplete != "" {
|
||||||
return routeRoutes, cobra.ShellCompDirectiveNoFileComp
|
for _, route := range routeRoutes {
|
||||||
|
if strings.HasPrefix(route, toComplete) {
|
||||||
|
filteredRoutes = append(filteredRoutes, route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filteredRoutes = routeRoutes
|
||||||
|
}
|
||||||
|
return slices.Clip(filteredRoutes), cobra.ShellCompDirectiveNoFileComp
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,15 @@ import (
|
|||||||
"gitea.libretechconsulting.com/50W/eia-api-go/pkg/eia"
|
"gitea.libretechconsulting.com/50W/eia-api-go/pkg/eia"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func GetRoute(cmd *cobra.Command, route string) (*eiaapi.FinalRoute, error) {
|
||||||
|
client, err := Client(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.GetRoute(cmd.Context(), route, eia.DefaultMethodSubs(cmd.Context()))
|
||||||
|
}
|
||||||
|
|
||||||
func GetFacet(cmd *cobra.Command, route string, facet string) (*eiaapi.FacetDetails, error) {
|
func GetFacet(cmd *cobra.Command, route string, facet string) (*eiaapi.FacetDetails, error) {
|
||||||
client, err := Client(cmd)
|
client, err := Client(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -36,8 +36,50 @@ var defaultMethodSubs = MethodSubs{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *Client) GetRoute(ctx context.Context, route string, subs *MethodSubs) (
|
||||||
|
*eiaapi.FinalRoute, error,
|
||||||
|
) {
|
||||||
|
eiaClient := reflect.ValueOf(client)
|
||||||
|
|
||||||
|
// Get the method for describing this facet
|
||||||
|
method := eiaClient.MethodByName(route)
|
||||||
|
if !method.IsValid() {
|
||||||
|
return nil, fmt.Errorf("method %s not found", route)
|
||||||
|
}
|
||||||
|
|
||||||
|
parser, err := getParser(route)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
args := prepMethodArgs(method, route, subs)
|
||||||
|
results := method.Call(args)
|
||||||
|
resp, err := getResponse(results)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := parseResponse(parser, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
desc, ok := result.Interface().(*eiaapi.FinalRouteResponseContainer)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("indescribable route returned")
|
||||||
|
}
|
||||||
|
|
||||||
|
if desc.Response == nil {
|
||||||
|
return nil, errors.New("no route response received")
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc.Response.Response, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Given an API route and a facet ID, retrieve information about the facet
|
// Given an API route and a facet ID, retrieve information about the facet
|
||||||
func (client *Client) GetFacet(ctx context.Context, route string, facet string, subs *MethodSubs) (*eiaapi.FacetDetails, error) {
|
func (client *Client) GetFacet(ctx context.Context, route string, facet string, subs *MethodSubs) (
|
||||||
|
*eiaapi.FacetDetails, error,
|
||||||
|
) {
|
||||||
eiaClient := reflect.ValueOf(client)
|
eiaClient := reflect.ValueOf(client)
|
||||||
|
|
||||||
// Get the method for describing this facet
|
// Get the method for describing this facet
|
||||||
@ -52,14 +94,9 @@ func (client *Client) GetFacet(ctx context.Context, route string, facet string,
|
|||||||
args := prepMethodArgs(method, methodName, subs)
|
args := prepMethodArgs(method, methodName, subs)
|
||||||
|
|
||||||
// Prepare a parser func for our facet response
|
// Prepare a parser func for our facet response
|
||||||
parserFunc, exists := eiaapi.ParseFunctionsMap[fmt.Sprintf("Parse%sResponse", methodName)]
|
parser, err := getParser(methodName)
|
||||||
if !exists {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parser func for %s not found", route)
|
return nil, err
|
||||||
}
|
|
||||||
|
|
||||||
parser := reflect.ValueOf(parserFunc)
|
|
||||||
if !parser.IsValid() {
|
|
||||||
return nil, errors.New("unable to find parser for facet response")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
results := method.Call(args)
|
results := method.Call(args)
|
||||||
@ -68,29 +105,12 @@ func (client *Client) GetFacet(ctx context.Context, route string, facet string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
results = parser.Call([]reflect.Value{reflect.ValueOf(resp)})
|
result, err := parseResponse(parser, resp)
|
||||||
if len(results) != 2 {
|
if err != nil {
|
||||||
return nil, errors.New("unexpected response while parsing facet response")
|
|
||||||
}
|
|
||||||
if err := checkCallErr(results[1]); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result := results[0]
|
facetDetails, ok := result.Interface().(*eiaapi.FacetDetailsContainer)
|
||||||
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")
|
|
||||||
}
|
|
||||||
|
|
||||||
facetDetails, ok := field.Interface().(*eiaapi.FacetDetailsContainer)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("response does not contain facet details")
|
return nil, errors.New("response does not contain facet details")
|
||||||
}
|
}
|
||||||
@ -103,7 +123,9 @@ func (client *Client) GetFacet(ctx context.Context, route string, facet string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return a list of facets given a named route
|
// Return a list of facets given a named route
|
||||||
func (client *Client) GetFacets(ctx context.Context, route string, subs *MethodSubs) (*eiaapi.FacetOptionList, error) {
|
func (client *Client) GetFacets(ctx context.Context, route string, subs *MethodSubs) (
|
||||||
|
*eiaapi.FacetOptionList, error,
|
||||||
|
) {
|
||||||
eiaClient := reflect.ValueOf(client)
|
eiaClient := reflect.ValueOf(client)
|
||||||
|
|
||||||
// Get the method by name
|
// Get the method by name
|
||||||
@ -115,14 +137,9 @@ func (client *Client) GetFacets(ctx context.Context, route string, subs *MethodS
|
|||||||
args := prepMethodArgs(method, route, subs)
|
args := prepMethodArgs(method, route, subs)
|
||||||
|
|
||||||
// Prepare a parser func for our facet response
|
// Prepare a parser func for our facet response
|
||||||
parserFunc, exists := eiaapi.ParseFunctionsMap[fmt.Sprintf("Parse%sResponse", route)]
|
parser, err := getParser(route)
|
||||||
if !exists {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parser func for %s not found", route)
|
return nil, err
|
||||||
}
|
|
||||||
|
|
||||||
parser := reflect.ValueOf(parserFunc)
|
|
||||||
if !parser.IsValid() {
|
|
||||||
return nil, errors.New("unable to find parser for facet response")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the API call
|
// Perform the API call
|
||||||
@ -137,32 +154,12 @@ func (client *Client) GetFacets(ctx context.Context, route string, subs *MethodS
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the parser with our response, then extract the JSON200 response,
|
result, err := parseResponse(parser, resp)
|
||||||
// and return the expected FacetOptiionsList from the container
|
if err != nil {
|
||||||
|
|
||||||
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result := results[0]
|
facetOptions, ok := result.Interface().(*eiaapi.FacetOptionListContainer)
|
||||||
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 {
|
if !ok {
|
||||||
return nil, errors.New("response does not contain facet options")
|
return nil, errors.New("response does not contain facet options")
|
||||||
}
|
}
|
||||||
@ -266,6 +263,34 @@ func prepMethodArgs(method reflect.Value, name string, subs *MethodSubs) []refle
|
|||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseResponse(parser reflect.Value, resp *http.Response) (reflect.Value, error) {
|
||||||
|
var result reflect.Value
|
||||||
|
|
||||||
|
results := parser.Call([]reflect.Value{reflect.ValueOf(resp)})
|
||||||
|
if len(results) != 2 {
|
||||||
|
return result, errors.New("unexpected response while parsing response")
|
||||||
|
}
|
||||||
|
if err := checkCallErr(results[1]); err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result = results[0]
|
||||||
|
if result.Kind() == reflect.Ptr {
|
||||||
|
result = result.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.Kind() != reflect.Struct {
|
||||||
|
return result, fmt.Errorf("unexpected parse result kind %s", result.Kind().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
field := result.FieldByName("JSON200")
|
||||||
|
if !field.IsValid() {
|
||||||
|
return result, errors.New("invalid facet data field in response")
|
||||||
|
}
|
||||||
|
|
||||||
|
return field, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getResponse(responses []reflect.Value) (*http.Response, error) {
|
func getResponse(responses []reflect.Value) (*http.Response, error) {
|
||||||
resp, ok := responses[0].Interface().(*http.Response)
|
resp, ok := responses[0].Interface().(*http.Response)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -279,6 +304,20 @@ func getResponse(responses []reflect.Value) (*http.Response, error) {
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getParser(forMethod string) (reflect.Value, error) {
|
||||||
|
parserFunc, exists := eiaapi.ParseFunctionsMap[fmt.Sprintf("Parse%sResponse", forMethod)]
|
||||||
|
if !exists {
|
||||||
|
return reflect.Value{}, fmt.Errorf("parser func for %s not found", forMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
parser := reflect.ValueOf(parserFunc)
|
||||||
|
if !parser.IsValid() {
|
||||||
|
return reflect.Value{}, errors.New("unable to find parser for facet response")
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser, nil
|
||||||
|
}
|
||||||
|
|
||||||
func checkCallErr(val reflect.Value) error {
|
func checkCallErr(val reflect.Value) error {
|
||||||
var err error
|
var err error
|
||||||
var ok bool
|
var ok bool
|
||||||
|
Loading…
Reference in New Issue
Block a user