Compojure-api, spec-tools, swagger,

146 views
Skip to first unread message

Dave Tenny

unread,
May 14, 2018, 3:46:36 PM5/14/18
to Clojure
I'm using compojure-api 2.0.0-alpha19, spec-tools 0.6.1, and trying to generate swagger pages with :spec coercion in compojure-api.

I know this is a work in progress but I'm not an expert in any of these tools and thought I'd ask here before I write pesky and likely incorrect issues in the Metosin repos.  I've done a fair bit of prismatic-schema enabled compojure-api and so was trying to translate some of that into a spec-ized implementation.  However i've either made a ton of mistakes (quite likely), or there's a lot of bugs, I'm not sure.

The following code fragments and annotated image show some of the problems I'm seeing.  Advice welcome. 

Basic specs, later aliased via 'db-jobs':

(s/def ::job-id nat-int?)
(s/def ::job-type #{:this-job :that-job :the-other-job})

Specs built on the above, later aliased via 'specs' in compojure-api declarations:
(s/def ::job-id  
 
(st/spec ::db-jobs/job-id
           
{:description "Specifies a Job ID, must be accompanied by a Firm ID for any valid use."}))


(s/def ::job-type
 
(st/spec ::db-jobs/job-type
           
{:description "Specifies the type of job to be dispatched to a suitable worker service node."}))


(s/def ::firm-id
 
(st/spec nat-int?
           
{:description "Specifies a Firm ID in the service database, or zero if there there is no specific firm."}))

Compojure-api code using the above three specs:

...
 
(:require
   
[clojure.spec.alpha :as s]
   
[compojure.api.core :as api-core]
   
[compojure.api.sweet :as sweet]
   
[compojure.route :as route]
   
[my.specs :as specs]
   
[spec-tools.core :as st]

...
(sweet/defroutes routes
 
(sweet/POST "/job/:firm-id" []
   
{:summary      "Enqueue a job"
     
:description  "Enqueue a job."
     
:path-params [firm-id :- ::specs/firm-id]
     
:body-params [job-type :- ::specs/job-type]
     
:responses   {201 {:description "Job enqueued." :schema ::specs/job-id}
                   
400 {:description "Invalid job type."
                       
:schema (st/spec string? {:description "Value of the unsupported job-type argument."})
                       
}}}
   
{:status 201 :body (impl/create-job! firm-id job-type)}))

...
 
(sweet/api
   
{:coercion :spec
   
:swagger {:data {;;:basePath "/"
                     
:info {:title "Job Scheduler"
                           
:description "Jobs"
                           
:version 1
                           
:contact {:name  "Pizza Eaters Inc." ...}}}
             
:ui "/docs/swagger"
             
:spec "/docs/swagger.json"
             
:options {:ui {:docExpansion "list"}}}}

The resulting swagger page (fragment) follows, annotated for discussion:


  1. For the Response Class presentation, it would be nice to get the description shown with the ::job-id type.
  2. The 'job-type' parameter name is not shown.
  3. The description of the 'job-type' parameter is not shown.
  4. The 201 response code data is missing from Response messages.
  5. (not highlighted)   :firm-id works as expected, whether it's because it's a :path-param or because it lacks the same degree of indirection in its spec definition I don't know.

Also note that
:path-params [firm-id :- (sweet/describe ::specs/firm-id "Firm identifier, or zero if there is no firm.")]
Does not produce a description in swagger, however the spec.tools code in the initial compojure-api code I presented works.  Bug or feature? (Seems like sweet/describe might be deprecated as we move to clojure.spec if we're using spec-tools).


Anyway, tips appreciated, and patience for obvious "user" mistakes.
Reply all
Reply to author
Forward
0 new messages