Fork me on GitHub
#pathom
<
2022-03-21
>
Reily Siegel16:03:38

I am looking into the feasibility of making a general purpose resolver generator for HTTP APIs in pathom3. I have come up with a very early stage example that can take a configuration and generate resolvers for each endpoint. The idea here is that each endpoint specifies the pathom attributes it needs for the header, query, body, and path parameters, and also what attributes the resolver outputs. It then generates a resolver that calls the API, and possibly transforms the result. Presumably this configuration could be automatically generated from API specifications like OpenAPI or Swagger, vastly simplifying the usage of pathom with external data sources. I have attached a sample configuration as a reply (so as not to clutter the channel). Do you think something like this is worth persuing?

Reily Siegel16:03:53

(resolvers
     { ;; Base URL for the API
      ::http/url ""
      ;; Function that processes an HTTP request, and returns a Clojure map with
      ;; strings as keys. Must accept :url, :query, :headers, :body, :method
      ::http/request!
      (fn [req]
        (j/read-value (:body @(client/request req))))
      ;; Specify the endpoints of the API
      ::http/endpoints
      [{;; The method of the endpoint
        ::http/method :get
        ;; Attributes that should be added to the path, in order. Items that are
        ;; not keywords are assumed to be constants.
        ::http/path   ["people" :person/id]
        ;; Attributes the resolver will output
        ;;
        ;; By default, pathom-http expects the API to produce a
        ;; string key of the name part of each keyword. For
        ;; example, for the keyword :person/name, pathom-http
        ;; will look for the string key "name" in the response.
        ::pco/output  [:person/name :person/height  :person/mass
                       :person/hair_color :person/eye_color
                       :person/gender :person/birth_year
                       :person/homeworld :person/films
                       :person/species :person/vehicles
                       :person/starships
                       :person/url]}
       {::http/method :get
        ::http/path   ["planets" :planet/id]
        ::pco/output  [:planet/name :planet/rotation_period
                       :planet/orbital_period :planet/diameter
                       :planet/climate :planet/gravity
                       :planet/terrain :planet/surface_water
                       :planet/population :planet/residents
                       :planet/films :planet/url]}]
      ;; Transformations that should be applied to attributes
      ;;
      ;; Here, SWAPI returns URLs to related attributes, rather than IDs. The
      ;; last-segment transform gets the last segment of a URL, and returns it
      ;; as the value of the attribute. The last-segments transform, similarly,
      ;; does the same thing, but works on an array of URLs, and requires an
      ;; attribute to associate with each ID. Transforms happen after
      ;; translations.
      ::http/transform
      {:person/homeworld last-segment
       :person/films     (last-segments :film/id)
       :person/species   (last-segments :species/id)
       :person/vehicles  (last-segments :vehicle/id)
       :person/starships (last-segments :starship/id)
       :planet/residents (last-segments :person/id)}})

wilkerlucio14:03:11

I think its great, usually the problem is around parameters, which sometimes are hard to figure which attributes they should map to. this is also a problem in GraphQL integration, that's why there is the manual mapping of it there