diff --git a/Makefile b/Makefile index f66adc5..1cd508e 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ schema: curl https://www.eia.gov/opendata/$(SCHEMA_ZIP) -o $(SCHEMA_DIR)/$(SCHEMA_ZIP) unzip -o $(SCHEMA_DIR)/$(SCHEMA_ZIP) -d $(SCHEMA_DIR) sed -E $(SED_INLINE) 's/responses\/data/schemas\/DataResponseContainer/g' $(SCHEMA_DIR)/$(SCHEMA_YML) - sed -E $(SED_INLINE) 's/responses\/route/schemas\/RouteResponseContainer/g' $(SCHEMA_DIR)/$(SCHEMA_YML) + sed -E $(SED_INLINE) 's/responses\/route/schemas\/RouteResponse/g' $(SCHEMA_DIR)/$(SCHEMA_YML) sed -E $(SED_INLINE) 's/responses\/facets/schemas\/FacetOptionListContainer/g' $(SCHEMA_DIR)/$(SCHEMA_YML) sed -E $(SED_INLINE) 's/responses\/facet/schemas\/FacetDetailsContainer/g' $(SCHEMA_DIR)/$(SCHEMA_YML) sed -E $(SED_INLINE) 's/responses\/final-route/schemas\/FinalRouteResponse/g' $(SCHEMA_DIR)/$(SCHEMA_YML) @@ -30,15 +30,9 @@ schema: # Generate code generate: go generate ./... -ifeq ($(IS_GNU_SED), true) - # Fix errors in generated code with GNU sed - sed -E -i 's/Total[[:space:]]+\*int/Total *string/g' $(CLIENT_GEN_FILE) - sed -E -i 's/Command[[:space:]]+\*\[\]string/Command *string/g' $(CLIENT_GEN_FILE) -else - # Fix errors in generated code with BSD sed - sed -E -i '' 's/Total[[:space:]]+\*int/Total *string/g' $(CLIENT_GEN_FILE) - sed -E -i '' 's/Command[[:space:]]+\*\[\]string/Command *string/g' $(CLIENT_GEN_FILE) -endif + sed -E $(SED_INLINE) 's/Total[[:space:]]+\*int/Total *string/g' $(CLIENT_GEN_FILE) + sed -E $(SED_INLINE) 's/Command[[:space:]]+\*\[\]string/Command *string/g' $(CLIENT_GEN_FILE) + sed -E $(SED_INLINE) 's/Routes[[:space:]]+\*\[\]string/Routes *[]Routes/g' $(CLIENT_GEN_FILE) # Pretty it up $(GO_FORMATTER) -w $(CLIENT_GEN_FILE) $(GO_FORMATTER) -w $(MAPPER_GEN_FILE) diff --git a/api/eiaapi.gen.go b/api/eiaapi.gen.go index 45501e7..8a655b8 100644 --- a/api/eiaapi.gen.go +++ b/api/eiaapi.gen.go @@ -127,19 +127,12 @@ type RouteResponse struct { Response *Routes `json:"response,omitempty"` } -// RouteResponseContainer defines model for RouteResponseContainer. -type RouteResponseContainer struct { - ApiVersion *string `json:"apiVersion,omitempty"` - Request *RouteRequest `json:"request,omitempty"` - Response *RouteResponse `json:"response,omitempty"` -} - // Routes defines model for Routes. type Routes struct { Description *string `json:"description,omitempty"` Id *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` - Routes *[]string `json:"routes,omitempty"` + Routes *[]Routes `json:"routes,omitempty"` } // Sort defines model for Sort. @@ -22708,7 +22701,7 @@ type ClientWithResponsesInterface interface { type GetV2Response struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -22730,7 +22723,7 @@ func (r GetV2Response) StatusCode() int { type GetV2AeoResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -22862,7 +22855,7 @@ func (r GetV2AeoRoute1FacetFacetIdResponse) StatusCode() int { type GetV2Co2EmissionsResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -23104,7 +23097,7 @@ func (r GetV2Co2EmissionsCo2EmissionsAndCarbonCoefficientsFacetFacetIdResponse) type GetV2CoalResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -23896,7 +23889,7 @@ func (r GetV2CoalReservesCapacityFacetFacetIdResponse) StatusCode() int { type GetV2CoalShipmentsResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -24688,7 +24681,7 @@ func (r GetV2CrudeOilImportsFacetFacetIdResponse) StatusCode() int { type GetV2DensifiedBiomassResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -25590,7 +25583,7 @@ func (r GetV2DensifiedBiomassWoodPelletPlantsFacetFacetIdResponse) StatusCode() type GetV2ElectricityResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -26052,7 +26045,7 @@ func (r GetV2ElectricityRetailSalesFacetFacetIdResponse) StatusCode() int { type GetV2ElectricityRtoResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -26954,7 +26947,7 @@ func (r GetV2ElectricityRtoRegionSubBaDataFacetFacetIdResponse) StatusCode() int type GetV2ElectricitySepResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -27746,7 +27739,7 @@ func (r GetV2ElectricityStateElectricityProfilesSummaryFacetFacetIdResponse) Sta type EIAAPIControllersDatasetAeoIeoIeoControllerIeoResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -27988,7 +27981,7 @@ func (r GetV2InternationalFacetFacetIdResponse) StatusCode() int { type GetV2NaturalGasResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -28010,7 +28003,7 @@ func (r GetV2NaturalGasResponse) StatusCode() int { type GetV2NaturalGasRoute1Response struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -28142,7 +28135,7 @@ func (r GetV2NaturalGasRoute1Route2FacetFacetIdResponse) StatusCode() int { type GetV2NuclearOutagesResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RouteResponseContainer + JSON200 *RouteResponse } // Status returns HTTPResponse.Status @@ -31762,7 +31755,7 @@ func ParseGetV2Response(rsp *http.Response) (*GetV2Response, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -31787,7 +31780,7 @@ func ParseGetV2AeoResponse(rsp *http.Response) (*GetV2AeoResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -31937,7 +31930,7 @@ func ParseGetV2Co2EmissionsResponse(rsp *http.Response) (*GetV2Co2EmissionsRespo switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -32212,7 +32205,7 @@ func ParseGetV2CoalResponse(rsp *http.Response) (*GetV2CoalResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -33112,7 +33105,7 @@ func ParseGetV2CoalShipmentsResponse(rsp *http.Response) (*GetV2CoalShipmentsRes switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -34012,7 +34005,7 @@ func ParseGetV2DensifiedBiomassResponse(rsp *http.Response) (*GetV2DensifiedBiom switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35037,7 +35030,7 @@ func ParseGetV2ElectricityResponse(rsp *http.Response) (*GetV2ElectricityRespons switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35562,7 +35555,7 @@ func ParseGetV2ElectricityRtoResponse(rsp *http.Response) (*GetV2ElectricityRtoR switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -36587,7 +36580,7 @@ func ParseGetV2ElectricitySepResponse(rsp *http.Response) (*GetV2ElectricitySepR switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -37487,7 +37480,7 @@ func ParseEIAAPIControllersDatasetAeoIeoIeoControllerIeoResponse(rsp *http.Respo switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -37762,7 +37755,7 @@ func ParseGetV2NaturalGasResponse(rsp *http.Response) (*GetV2NaturalGasResponse, switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -37787,7 +37780,7 @@ func ParseGetV2NaturalGasRoute1Response(rsp *http.Response) (*GetV2NaturalGasRou switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -37937,7 +37930,7 @@ func ParseGetV2NuclearOutagesResponse(rsp *http.Response) (*GetV2NuclearOutagesR switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RouteResponseContainer + var dest RouteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/cmd/eia-client/cmd/get/get_route.go b/cmd/eia-client/cmd/get/get_route.go index 74ec535..d52e5c4 100644 --- a/cmd/eia-client/cmd/get/get_route.go +++ b/cmd/eia-client/cmd/get/get_route.go @@ -36,15 +36,24 @@ func RunGetRouteCmd(cmd *cobra.Command, args []string) { logger := util.Logger(cmd) logger.Info().Str("route", args[0]).Msg("getting route description") - route, err := util.GetRoute(cmd, args[0]) + finalRoute, route, err := util.GetRoute(cmd, args[0]) if err != nil { logger.Fatal().Err(err).Send() } - bytes, _ := yaml.Marshal(route) - fmt.Println(string(util.PrettyBytes(&util.PrettyOpts{ - Bytes: append([]byte(fmt.Sprintf("name: %s\n", args[0])), bytes...), - }))) + if route != nil { + bytes, _ := yaml.Marshal(route) + fmt.Println(string(util.PrettyBytes(&util.PrettyOpts{ + Bytes: append([]byte(fmt.Sprintf("name: %s\ntype: routes\n", args[0])), bytes...), + }))) + } + + if finalRoute != nil { + bytes, _ := yaml.Marshal(finalRoute) + fmt.Println(string(util.PrettyBytes(&util.PrettyOpts{ + Bytes: append([]byte(fmt.Sprintf("name: %s\ntype: finalRoute\n", args[0])), bytes...), + }))) + } } func completeRouteRoutes(cmd *cobra.Command, args []string, toComplete string) ( diff --git a/cmd/eia-client/internal/util/util_reflect.go b/cmd/eia-client/internal/util/util_reflect.go index d94d129..b614bff 100644 --- a/cmd/eia-client/internal/util/util_reflect.go +++ b/cmd/eia-client/internal/util/util_reflect.go @@ -7,13 +7,13 @@ import ( "gitea.libretechconsulting.com/50W/eia-api-go/pkg/eia" ) -func GetRoute(cmd *cobra.Command, route string) (*eiaapi.FinalRoute, error) { +func GetRoute(cmd *cobra.Command, route string) (*eiaapi.FinalRoute, *eiaapi.Routes, error) { client, err := Client(cmd) if err != nil { - return nil, err + return nil, nil, err } - return client.GetRoute(cmd.Context(), route, eia.DefaultMethodSubs(cmd.Context())) + return client.GetRoutesOrFinalRoute(cmd.Context(), route, eia.DefaultMethodSubs(cmd.Context())) } func GetFacet(cmd *cobra.Command, route string, facet string) (*eiaapi.FacetDetails, error) { diff --git a/pkg/eia/eia_reflection.go b/pkg/eia/eia_reflection.go index 1da22a0..585ca4c 100644 --- a/pkg/eia/eia_reflection.go +++ b/pkg/eia/eia_reflection.go @@ -2,7 +2,6 @@ package eia import ( "context" - "encoding/json" "errors" "fmt" "net/http" @@ -43,20 +42,22 @@ var defaultMethodSubs = MethodSubs{ } // Retrieve information for a named Route (e.g. GetAeoV2Route1) -func (client *Client) GetRoute(ctx context.Context, route string, subs *MethodSubs) ( - *eiaapi.FinalRoute, error, +// Returns a *eiaapi.Routes if this is not a final route, otherwise returns +// a final route response +func (client *Client) GetRoutesOrFinalRoute(ctx context.Context, route string, subs *MethodSubs) ( + *eiaapi.FinalRoute, *eiaapi.Routes, 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) + return nil, nil, fmt.Errorf("method %s not found", route) } parser, err := getParser(route) if err != nil { - return nil, err + return nil, nil, err } args := prepMethodArgs(method, route, subs) @@ -64,33 +65,57 @@ func (client *Client) GetRoute(ctx context.Context, route string, subs *MethodSu results := method.Call(args) resp, err := getResponse(results) if err != nil { - return nil, err + return nil, nil, err } result, err := ParseResponse(&ParseOpts{ Parser: parser, Resp: resp, - BodyOnly: true, + JsonOnly: true, }) if err != nil { - return nil, err + return nil, nil, err } - // The api doesn't actually return what the swagger spec - // tells you it is going to return, so we need to do this - // manually for routes - frr := new(eiaapi.FinalRouteResponse) - if err = json.Unmarshal( - result.Interface().([]uint8), frr, - ); err != nil { - return nil, err + // First, see if we have a Final Route + frr, err := getFRR(result) + if err == nil && frr.Response != nil { + return frr.Response, nil, nil } - if frr.Response == nil { - return nil, errors.New("no route response received") + // Then, see if we have an intermediate route + rr, err := getRR(result) + if err == nil && rr.Response != nil { + return nil, rr.Response, nil } - return frr.Response, nil + return nil, nil, errors.New("No route or final route fount in response") +} + +func getRR(json200 reflect.Value) (*eiaapi.RouteResponse, error) { + rr, ok := json200.Interface().(*eiaapi.RouteResponse) + if !ok { + return nil, errors.New("response does not contain route response container") + } + + if rr == nil { + return nil, errors.New("no route response found") + } + + return rr, nil +} + +func getFRR(json200 reflect.Value) (*eiaapi.FinalRouteResponse, error) { + frr, ok := json200.Interface().(*eiaapi.FinalRouteResponse) + if !ok { + return nil, errors.New("response does not contain final route response") + } + + if frr == nil { + return nil, errors.New("no final route response found") + } + + return frr, nil } // Given an API route and a facet ID, retrieve information about the facet diff --git a/schema/eia-api-swagger.yaml b/schema/eia-api-swagger.yaml index 6db02e4..d1660fc 100644 --- a/schema/eia-api-swagger.yaml +++ b/schema/eia-api-swagger.yaml @@ -1008,7 +1008,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' parameters: - $ref: '#/components/parameters/route1' @@ -1313,7 +1313,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/ieo: get: tags: @@ -1325,7 +1325,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/co2-emissions/co2-emissions-aggregates: get: tags: @@ -1480,7 +1480,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/coal/aggregate-production: get: tags: @@ -1564,7 +1564,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/coal/consumption-and-quality: get: tags: @@ -2425,7 +2425,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/crude-oil-imports: get: tags: @@ -2651,7 +2651,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/densified-biomass/export-sales-and-price: get: tags: @@ -3090,7 +3090,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/electricity/facility-fuel: get: tags: @@ -3742,7 +3742,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/electricity/state-electricity-profiles/source-disposition: get: tags: @@ -4252,7 +4252,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/electricity/rto/fuel-type-data: get: tags: @@ -4691,7 +4691,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/nuclear-outages/us-nuclear-outages: get: tags: @@ -4773,7 +4773,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' /v2/total-energy: get: tags: @@ -4855,7 +4855,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RouteResponseContainer' + $ref: '#/components/schemas/RouteResponse' components: schemas: Routes: