This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-15
Channels
- # adventofcode (80)
- # beginners (94)
- # biff (19)
- # cider (74)
- # clj-kondo (11)
- # cljs-dev (7)
- # clojure (110)
- # clojure-austin (3)
- # clojure-australia (1)
- # clojure-belgium (1)
- # clojure-china (1)
- # clojure-europe (83)
- # clojure-filipino (1)
- # clojure-hk (1)
- # clojure-indonesia (1)
- # clojure-japan (1)
- # clojure-korea (1)
- # clojure-my (1)
- # clojure-nl (1)
- # clojure-norway (4)
- # clojure-sg (1)
- # clojure-taiwan (1)
- # clojure-uk (2)
- # cursive (3)
- # data-science (8)
- # datalevin (8)
- # emacs (18)
- # etaoin (5)
- # graalvm (1)
- # holy-lambda (3)
- # honeysql (1)
- # jackdaw (10)
- # java (10)
- # jobs (3)
- # luminus (9)
- # malli (106)
- # off-topic (88)
- # polylith (8)
- # portal (2)
- # re-frame (50)
- # reagent (11)
- # reitit (74)
- # remote-jobs (1)
- # shadow-cljs (46)
- # tools-deps (26)
- # xtdb (49)
Hi! Regarding https://cljdoc.org/d/metosin/reitit/0.5.18/doc/advanced/dev-workflow#an-easy-fix, how does that work with reitit.ring/ring-handler
? The handler is only constructed once. Thanks!
thanks @U11EL3P9U, having similar utils in projects, SHOULD be part of reitit
With that running in my local setup, I can change any route, handler whatever...re-eval the function and things magically just work 🙂
(re-eval the handler function, or something that it calls, not the static-ring-handler/reply-friendly-ring-handler...)
here’s what I have:
(if dev-mode
(fn
([request] ((create-handler) request))
([request respond raise] ((create-handler) request respond raise)))
(create-handler))
maybe a reitit.ring/dev-handler
function that takes a 0-arity fn to create the actual ring-handler?
thanks a lot!
How does one coerce string to localDatetime using reitit + malli?
{:get {:summary "Gives you link for specific match highlights"
:parameters {:query [:map
[:match-id uuid?]
[:date [:fn (fn [d] (java.time.LocalDate/parse d))]]]}
:responses {200 {:body {:link-random string?}}}
:handler (fn [{{data :query} :parameters}]
(prn data)
{:status 200
:body {:link-random "aa"}})}
}
I am using reitit + malli + swagger example.
Why does uuid work but date doesn't?
{:match-id #uuid "2baf6715-b58e-4ec1-b02a-b938bec2cd7d", :date "2022-10-10"}
(def muuntaja-instance
(m/create
(-> m/default-options
(assoc-in [:formats "application/json" :decoder-opts] {:decode-key-fn csk/->kebab-case-keyword
;;<<???>> #(java.time.LocalDate/parse %)
})
(assoc-in [:formats "application/json" :encoder-opts] {:encode-key-fn csk/->camelCaseString
:date-format "yyyy-MM-dd"})
#_(assoc-in
[:formats "application/json" :encoder-opts]
{:date-format "yyyy-MM-dd"}))))
Something like this?Yeah i can't figure it out
(malli/coerce :int "invalid" mt/string-transformer)
Syntax error compiling at (src/highlights/server.clj:56:3).
No such var: malli/coerce
I am using malli 0.9.2(def date-decode (malli/decoder [:fn #(java.time.LocalDate/parse %)] mt/string-transformer))
(date-decode "2022-10-10")
=> "2022-10-10"
The malli docs are dense but all the information is there, I just had to read them several times slowly 😞
But you need to understand what schema properties are, how decoders are specified via properties, and how to use them
Truth is i am using malli for validation in other places. I wanted to reuse same schema.
[:map {:closed true} [:match-id [:fn {:description "Match id", :swagger/default "7e1840af-7758-4baa-957b-cc1bdd753303", :swagger/type "string", :swagger/format "uuid", :error/message "Invalid match-id"} #function[highlights.validation/valid-uuid-as-str?]]] [:date [:fn {:description "Date when the match happened", :swagger/default "2022-10-10", :swagger/type "string", :swagger/format "date", :error/message "Invalid date"} #function[highlights.validation/valid-date-as-str?]]]]
when i failed to make any progress i reduced complexity and failed to do even string -> date conversion.(m/coerce
[:fn
{:decode/string #(java.time.LocalDate/parse %)
:decode/json #(java.time.LocalDate/parse %)}
#(instance? java.time.LocalDate %)]
"2022-10-10"
(mt/string-transformer))
; => #object[java.time.LocalDate 0x2bbd77fb "2022-10-10"]
@U055NJ5CC where is coerce located at? It's not in malli.core?
in core, just unreleased 😉 https://github.com/metosin/malli/blob/master/CHANGELOG.md#unreleased
@U45SLGVHV here you go
(require '[malli.core :as m] '[malli.transform :as mt])
(import java.time.LocalDate)
(def local-date
(m/-simple-schema
{:pred #(instance? LocalDate %)
:type-properties
{:decode/string #(try
(LocalDate/parse %)
(catch Exception _ %))}}))
(m/decode local-date "2020-10-01" mt/string-transformer)
Oh little bit of cheating, i thought i was going mad because i couldn't find it my v0.9.2 of malli Thanks a lot. Basically adding
[:fn
{:decode/string #(java.time.LocalDate/parse %)
:decode/json #(java.time.LocalDate/parse %)}
#(instance? java.time.LocalDate %)]
to existing schema solved it@UK0810AQ2 thanks for this but how does it differ from the above?
maybe we should finish adding the https://github.com/metosin/malli/pull/545 to malli, copy-pasting what is needed between projects :thinking_face:
we can start adding properties, such as the expected pattern, min and max date, those are for specific instances of the schema. Additionally we could add more things to the schema, put it in a registry, and make it less opaque
@U055NJ5CC @UK0810AQ2 why am i allowed to make wrong input in swagger and input doesn't get to be red? also if i try execute it fails on the server. If i change uuid to something bad it doesn't even allow me to 'execute'
what is different between
[:map {:closed true} [:match-id [:fn {:description "Match id", :swagger/default "7e1840af-7758-4baa-957b-cc1bdd753303", :error/message "Invalid match-id"} #function[clojure.core/uuid?]]]]
and
just putting
[:map [:match-id uuid?]]
Second one makes swagger behave how i expect it. If i put values in input that are not uuid i can't even execute the request.
Is there a way for me to make a custom schema that behaves the same way native one does? With input validation and all?What matters isn't the predicate function, but how it's externalized over json schema to the swagger UI
Thanks i get that but i found weird behaviors. I've been on this whole day so maybe fatigue is taking it's toll. I will step out and try again tomorrow Thanks both for your time and effort
I think i figured it out for date 🙂 You were right i had to look on how description was done in swagger.
[:fn {:swagger/description "Date when the match happened"
:swagger/default "2022-10-10"
:swagger/type "string"
:swagger/format "date"
:swagger/pattern #"^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$"
:decode/string #(java.time.LocalDate/parse %)
:decode/json #(java.time.LocalDate/parse %)
:error/message "Invalid date"}
date?]
working example on how to have input validation in swagger for others.
Pattern is needed to have full control over date format type string.Regarding UUID
it seems to be that as soon as you put [:fn...
in your schema you need to provide decoders and helpful defaults are out.
So you need to specify all json-schema goodies you need.
👍 related to :fn
- it has no type so you have to tell everything yourself. There is an old issue of type-tagging schemas easily, which would allow you to say: [:fn {:type :int} (fn [x] …]]
and all schema applications (transforming, generators, json-schema, …) would know it’s an :int
.
what is different between
[:map {:closed true} [:match-id [:fn {:description "Match id", :swagger/default "7e1840af-7758-4baa-957b-cc1bdd753303", :error/message "Invalid match-id"} #function[clojure.core/uuid?]]]]
and
just putting
[:map [:match-id uuid?]]
Second one makes swagger behave how i expect it. If i put values in input that are not uuid i can't even execute the request.
Is there a way for me to make a custom schema that behaves the same way native one does? With input validation and all?Hey. Is it possible to somehow reload routes without restarting the whole server? I'm thinking whether I can have a running websocket but then reload some REST routes :thinking_face:
#'app
binding might work for me :thinking_face:
Ah, that's quite neat 😄 Thanks!