Publish intermediate paths by default #175

Change current default of Ring routers and frontend to publish both leaf paths and intermediate paths as endpoints.
`:name` in route data is required for intermediate frontend routes, and `:handler` for Ring routes.
This commit is contained in:
Toni Vanhala 2019-10-25 18:17:22 +03:00
parent 841f581a17
commit c42f76af92
3 changed files with 69 additions and 3 deletions

View file

@ -265,6 +265,61 @@
{:endpoint data
:inherit {}}))
(defn dissoc-in
"Dissociates an entry from a nested associative structure returning a new
nested structure. `keys` is a sequence of keys. Any empty maps that result
will not be present in the new structure."
[m [k & ks]]
(if ks
(if-let [nextmap (get m k)]
(let [newmap (dissoc-in nextmap ks)]
(if (seq newmap)
(assoc m k newmap)
(dissoc m k)))
m)
(dissoc m k)))
(defn transform-inherited-data
[transform-configs data]
(let [short-hands {:consume #(dissoc-in %1 %2)
:inherit (fn [d _] d)}]
(reduce
(fn [acc {:keys [kss transform]}]
(let [transform (or (get short-hands transform)
transform)]
(reduce (fn [{:keys [inherit endpoint]} ks]
(if (get-in inherit ks)
{:inherit (transform inherit ks) :endpoint data}
{:inherit inherit :endpoint endpoint}))
acc
kss)))
{:endpoint nil :inherit data}
transform-configs)))
(defn mk-intermediate-endpoint-transform
"Make function that returns map for valid endpoints, which are either a leaf path in
the route tree, or have route data for one or more of nested key sequences.
The returned map will contain data for the current endpoint under `:endpoint` and data to be
inherited for children under `:inherit`.
Provided arg should be a vector of maps with :kss, a seq of seq of keys, and :transform. Expanded route data
will be queried with each of the key sequences. If data exists in the key sequence, the provided `:transform` function
is called with `(transform data ks)`, so that the result is to be passed to children.
Query is repeated for each seq of seq with the same transform, moving on to the next transform.
All transforms are performed before passing data to children.
If none of the key seqs match, then falsy is returned to indicate that the path should
not be used as an endpoint.
Optionally, `:transform` may be specified with keywords `:consume` as short-hand for removing the matching data,
or `:inherit` for passing the data as-is to children."
[transform-configs]
(fn [prev-path path meta data childs]
(or (leaf-endpoint prev-path path meta data childs)
(and (map? data)
(seq childs)
(transform-inherited-data transform-configs data)))))
(defmacro goog-extend [type base-type ctor & methods]
`(do
(def ~type (fn ~@ctor))

View file

@ -2,7 +2,8 @@
(:require [clojure.set :as set]
[reitit.coercion :as coercion]
[reitit.coercion :as rc]
[reitit.core :as r])
[reitit.core :as r]
[reitit.impl :as impl])
(:import goog.Uri
goog.Uri.QueryData))
@ -45,13 +46,17 @@
([router name path-params]
(r/match-by-name router name path-params)))
(def frontend-endpoint (impl/mk-intermediate-endpoint-transform [{:kss [[:name]]
:transform :consume}]))
(defn router
"Create a `reitit.core.router` from raw route data and optionally an options map.
Enables request coercion. See [[reitit.core/router]] for details on options."
([raw-routes]
(router raw-routes {}))
([raw-routes opts]
(r/router raw-routes (merge {:compile rc/compile-request-coercers} opts))))
(r/router raw-routes (merge {:compile rc/compile-request-coercers
:endpoint frontend-endpoint} opts))))
(defn match-by-name!
"Logs problems using console.warn"

View file

@ -65,6 +65,11 @@
([request respond _]
(respond (handle request))))))
(def ring-endpoint (impl/mk-intermediate-endpoint-transform [{:kss (for [method http-methods] [method :handler])
:transform :inherit}
{:kss [[:name]]
:transform :consume}]))
;;
;; public api
;;
@ -93,7 +98,8 @@
([data opts]
(let [opts (merge {:coerce coerce-handler
:compile compile-result
::default-options-handler default-options-handler} opts)]
::default-options-handler default-options-handler
:endpoint ring-endpoint} opts)]
(r/router data opts))))
(defn routes