Fork me on GitHub
#yada
<
2016-06-30
>
Rachel Westmacott07:06:01

@malcolmsparks: I'm just following https://juxt.pro/yada/manual/install.html and got to this bit

(def svr
  (server
    (routes
      ["/"
        [
          ["hello" (as-resource "Hello World!")]
          ["test" {:produces "text/plain"
                   :response "This is a test!"}]]])
    {:port 3000}))
and the error I get is
CompilerException clojure.lang.ExceptionInfo: Cannot turn resource-model into resource, because it doesn't conform to a resource-model schema {:resource-model {:last-modified #inst "2016-06-30T07:05:42.198-00:00", :version "Hello World!"}, :error {:methods missing-required-key, (not (namespace :last-modified)) invalid-key, (not (namespace :version)) invalid-key}}, compiling:(form-init551993252150942307.clj:3:5) 

ilukinov07:06:40

scroll up a little bit, answer from the author - use edge

malcolmsparks07:06:17

@peterwestmacott: thanks Peter, that's unexpected, but the code looks wrong to me. I think it's a doc bug

ilukinov07:06:54

@malcolmsparks: are you kidding me?

malcolmsparks07:06:00

@ilukinov: I'm not kidding. yada is still a work in progress. It is developed in the open so early adopters can use it and provide feedback. Docs are hard to keep up to date when a project is still in development but I am trying my best to address this. As I said, the quickstart is much more recent and only needs a bit of eork on the mutation and parameters sections now

ilukinov07:06:42

I understand that, but instead of saying that docs are outdated it would be better to just give an answer on how to fix this particular problem, how to create this first resource and start using your lib in OUR projects. This doc is face of your lib and has a power to attract or detract people to using your lib.I’ve ended up using liberator and ring. Because of this outdated manual.

malcolmsparks07:06:45

I have given an answer to this question, which is to download Edge, run it, see how it works, and apply that learning to your own projects. But thanks for pointing out the error, I've got an hour train journey this morning I can look into it and fix it.

Rachel Westmacott07:06:20

@malcolmsparks: thanks, I’ll give that a try next time I’m looking at yada.

Rachel Westmacott07:06:14

and thanks for giving us all free early access to your library

malcolmsparks08:06:58

Sorry about the doc status. I'll fix this particular issue today

Rachel Westmacott08:06:28

no worries, you’ve said its work in progress and there’s clearly lots to be done. If the focus is on making ‘edge’ the best onboarding ramp then I’m happy to jump in there instead for now

malcolmsparks08:06:45

Yes. Obviously documentation produces few compiler errors. I've attempted literate prog things in the past but it's still a lot of work. The reason Edge is a better approach right now is that it has to compile to work

malcolmsparks08:06:03

I did consider dropping the install chapter entirely but I think it still has a place once I've fixed the doc bugs

martinklepsch08:06:32

Definitely intending to go to Clojutre again 🙂 Also managed to send in a proposal last minute 🙂

ijbriscoe11:06:23

Hi @malcolmsparks . I've looked at the code for generating the link to the Swagger UI in the selmer template, and have got a long way towards being able to generate the full URL for the Swagger UI + my swagger.json, so that I can ultimately provide an endpoint that redirects there.

ijbriscoe11:06:14

Just a final check to make sure that I'm not duplicating effort here.

ijbriscoe11:06:35

I'm pretty sure the swaggered function provided an endpoint to do this, but I couldn't get it to work properly

ijbriscoe12:06:27

Just studied the code in the Swaggered record:

;; Redirect to swagger.json
          (#{"" "/"} (:remainder m))
          (succeed
           (reify Ring
             (request [_ req _]
               (redirect (str (:uri req)
                              (subs "/swagger/index.html?url=" (count (:remainder m)))
                              (or (:basePath spec) "") "/swagger.json"))))
           (assoc m :remainder ""))
and this does the redirect I've seen. Also worked out the role of the :basePath key in the map you provide the swaggered function, so should be able to get this to work.

ijbriscoe12:06:59

Interesting that you show two ways to provide swagger.json; one using swaggered (for the hello-routes) and a more verbose approach, using swagger-spec-resource and swagger-spec from yada.swagger, for the phonebook-api.

ijbriscoe13:06:27

I've got Swagger integration working, using the swaggered function:

(def api ["/api"
           [["/service1" (yada/yada "service1")]
            ["/service2" (yada/yada "service2")]]])


(def routes [""
             [api
              ["" (yada/swaggered api)]
              [true (yada/yada "catchall")]]])

ijbriscoe13:06:38

The key for me was that you can use "" as a pattern

ijbriscoe13:06:19

(yada/swaggered routes) has to be used on the right side of a RoutePair, which tripped me up a lot

ijbriscoe13:06:22

Now, I can do e.g. curl -i localhost:9050/ and yada will redirect to http://localhost:9050/swagger/index.html?url=/swagger.json

ijbriscoe13:06:09

If you want to put the swaggered function under a non-blank path, e.g.

(def routes [""
             [api
              ["/docs" (yada/swaggered api {:basePath "/docs"})]
              [true (yada/yada "catchall")]]])

ijbriscoe13:06:22

Note, that without the :basePath, the url query string parameter will be wrong

ijbriscoe13:06:02

So, curl -i localhost:9050/docs will redirect to

ijbriscoe13:06:33

Hope this helps anyone who has struggled to get this to work

griff13:06:02

@ijbriscoe: I actually believe that setup like you have it your api is defined twice. Both at /api/service1 and /docs/api/service1

ijbriscoe13:06:54

/api/service delivers the actual API, while /docs/api... delivers the documentation

ijbriscoe13:06:21

The best pattern I've found (and one you see used in Edge) is to define the API outside the main routes definition; that way you include it once to deliver the API, and then pass it into the swaggered function to generate the Swagger UI and swagger.json endpoints

ijbriscoe13:06:41

You only need the api, routes and this, to try it out in a REPL:

(def s (http/start-server (yada.handler/as-handler routes) {:port 9050}))

ijbriscoe13:06:47

If you need help with the requires, let me know

griff13:06:42

What I mean is that the swaggered function wraps and includes the routes as well as the swagger documentation.

ijbriscoe13:06:39

How come you see this code in Edge:

;; Hello World!
    (hello-routes)
    (other-hello-routes)

    (phonebook-routes db config)

    ["/api" (-> (hello-routes)
                ;; Wrap this route structure in a Swagger
                ;; wrapper. This introspects the data model and
                ;; provides a swagger.json file, used by Swagger UI
                ;; and other tools.
                (yada/swaggered
                 {:info {:title "Hello World!"
                         :version "1.0"
                         :description "An API on the classic example"}
                  :basePath "/api"})
                ;; Tag it so we can create an href to this API
                (tag :edge.resources/api))]

ijbriscoe13:06:05

I will try out what you say... just in case

ijbriscoe13:06:39

Nope - I removed the non-wrapped api from the routes, now when I try GET /api/service1, my catch-all is matched

griff13:06:22

Well did you try /docs/api/service1?

ijbriscoe13:06:32

Ah... that does work. However. it's not the URL I want to publish my API on

ijbriscoe13:06:47

Interesting to know that though - thanks

griff13:06:06

` (def api ["" [["/service1" (yada/yada "service1")] ["/service2" (yada/yada "service2")]]]) (def routes [“/api" [["" (yada/swaggered api {:basePath “/api/"})] [true (yada/yada "catchall")]]])

griff13:06:22

I do it like that

ijbriscoe13:06:40

That'd work for us 🙂

ijbriscoe13:06:09

Just tried it out - nice! Also keeps the routes composability that I need, so thanks