Spec form metadata is lost on visiting it during Swagger UI generation

Offen
#417 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
45/100
Issue-Typ
Bug
Klarheit
Größtenteils klar
Aktivitätsstatus
Veraltet
Tech-Stack
clojure
Bereich
api

Rechercherichtung

Beginnen Sie mit spec-tools.visitor/visit und spec-tools.impl/extract-form und führen Sie anschließend die bereitgestellte Reproduktion gegen den Swagger UI-Generierungspfad für benutzerdefinierte Specs in :return und :body aus. Vergleichen Sie die Metadaten des extrahierten Formulars mit dem funktionierenden Fall für s/coll-of; abgeschlossen ist die Aufgabe, wenn die erwarteten Metadaten für den benutzerdefinierten Visitor weiterhin verfügbar sind.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Library Version(s)

2.0.0-alpha29

Problem

I need to redefine spec-tools.visitor/visit for my custom spec to change how spec is shown in Swagger UI. E.g. I have closed-keys custom spec, but want to visit it as s/keys, so that Swagger UI generates appropriate model examples from my spec.

Now, it can be cumbersome to parse the custom spec form to implement its visiting. So I want instead to rely on the metadata attached to the spec form (such easy to use metadata can be conveniently generated by closed-keys macro). I.e.:

(defmethod st-visitor/visit-spec `closed-keys
  [spec accept options]
  (let [form (st-impl/extract-form spec)
        keys-form <generate from (meta form)>]
   (st-visitor/visit-spec keys-form accept options)))

But this currently doesn't work because (meta form) is always nil in this function.

I only managed to trace it back to spec-tools.visitor/visit function: it seems to get already crooked spec with no metadata in its form.

The issue is reproducible for custom specs used in :return and :body. I didn't test other places.

Steps:

  1. Code:
(ns app.foo.handler
  (:require [compojure.api.sweet :as c]
            [ring.util.http-response :as r]
            [clojure.spec.alpha :as s]
            [spec-tools.visitor :as st-visitor]
            [spec-tools.impl :as st-impl]))

; Helper to redefine spec form
(defn -with-form
  [spec form]
  {:pre [(s/spec? spec)]}
  (reify s/Spec
    (describe* [_] form)

    ; Do not modify other methods
    (conform* [_ x] (s/conform* spec x))
    (unform* [_ y] (s/unform* spec y))
    (explain* [_ path via in x] (s/explain* spec path via in x))
    (gen* [_ overrides path rmap] (s/gen* spec overrides path rmap))
    (with-gen* [_ gfn] (s/with-gen* spec gfn))))

; Create spec with a custom form and metadata attached to the form
(s/def ::my-spec (-> (s/spec int?)
                     (-with-form
                       (with-meta (list 'my-spec 1 2 3) {:my-spec-form-meta [1 2 3]}))))

; Custom visiting which relies on metadata from the form
(defmethod st-visitor/visit-spec 'my-spec
  [spec _accept _options]
  (let [form (st-impl/extract-form spec)]
    (prn :VISITED-FORM form :META (meta form))
    nil))

; Handler code
(c/context "/my" []
    (c/POST "/foo" []
      :return ::my-spec
      ;:body [x ::my-spec]
      (r/ok)))
  1. Run it and navigate to Swagger UI URL.
  2. Check console output.

Expected:

:VISITED-FORM (my-spec 1 2 3) :META {:my-spec-form-meta [1 2 3]}

Actual:

:VISITED-FORM (my-spec 1 2 3) :META nil

Workaround:

My current workaround is to attach metadata to the first symbol in the form instead of the whole form. Also in another case I just parse the form instead of relying on its metadata.

Interestingly, the issue is not reproducible when custom spec is "wrapped" by some other spec, specifically (s/coll-of ::my-spec) doesn't seem to have a problem.

Vorherrschende Sprache
Clojure
Sterne
1.1k
Forks
143
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus metosin/compojure-api

Alle Issues in metosin/compojure-api

Ähnliche Issues

Weitere Issues zu Clojure

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.