chore(malli)_: New map schema to reduce optional/maybe verbosity
This commit is contained in:
parent
a92b50afea
commit
8df314b2c2
|
@ -6,15 +6,13 @@
|
|||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:full-name {:optional true} [:maybe string?]]
|
||||
[:size {:optional true} [:maybe (into [:enum] (keys style/sizes))]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:static? {:optional true} [:maybe boolean?]]
|
||||
[:status-indicator? {:optional true} [:maybe boolean?]]
|
||||
[:online? {:optional true} [:maybe boolean?]]
|
||||
[:ring? {:optional true} [:maybe boolean?]]
|
||||
[:profile-picture
|
||||
{:optional true}
|
||||
[:maybe :schema.quo/profile-picture-source]]]]]
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:full-name string?]
|
||||
[:size (into [:enum] (keys style/sizes))]
|
||||
[:customization-color :schema.common/customization-color]
|
||||
[:static? boolean?]
|
||||
[:status-indicator? boolean?]
|
||||
[:online? boolean?]
|
||||
[:ring? boolean?]
|
||||
[:profile-picture :schema.quo/profile-picture-source]]]]
|
||||
:any])
|
||||
|
|
|
@ -3,17 +3,16 @@
|
|||
(def ?schema
|
||||
[:=>
|
||||
[:cat
|
||||
[:map {:closed true}
|
||||
[:accessibility-label {:optional true} [:maybe :keyword]]
|
||||
[:type {:optional true} [:maybe [:enum :main :danger]]]
|
||||
[:action {:optional true} [:maybe [:enum :arrow :toggle :input]]]
|
||||
[:icon {:optional true} [:maybe :keyword]]
|
||||
[:description {:optional true} [:maybe :string]]
|
||||
[:state {:optional true} [:maybe [:enum :selected]]]
|
||||
[:title {:optional true} :string]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:input-props {:optional true} [:maybe :map]]
|
||||
[:customization-color {:optional true}
|
||||
[:maybe :schema.common/customization-color]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]]]
|
||||
[:schema.common/map {:closed true :optional true :maybe true}
|
||||
[:accessibility-label :keyword]
|
||||
[:type [:enum :main :danger]]
|
||||
[:action [:enum :arrow :toggle :input]]
|
||||
[:icon :keyword]
|
||||
[:description :string]
|
||||
[:state [:enum :selected]]
|
||||
[:title {:no-maybe true} :string]
|
||||
[:on-press fn?]
|
||||
[:input-props :map]
|
||||
[:customization-color :schema.common/customization-color]
|
||||
[:blur? :boolean]]]
|
||||
:any])
|
||||
|
|
|
@ -20,15 +20,14 @@
|
|||
[:on-options-press {:optional true} [:maybe fn?]]])
|
||||
|
||||
(def ^:private ?base
|
||||
[:map
|
||||
[:type {:optional true}
|
||||
[:enum :default :tag :action :balance-neutral :balance-negative :balance-positive]]
|
||||
[:state {:optional true} [:enum :default :selected :active]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:title-icon {:optional true} [:maybe :keyword]]
|
||||
[:account-props
|
||||
[:schema.common/map {:optional true}
|
||||
[:type [:enum :default :tag :action :balance-neutral :balance-negative :balance-positive]]
|
||||
[:state [:enum :default :selected :active]]
|
||||
[:blur? [:maybe :boolean]]
|
||||
[:customization-color [:maybe :schema.common/customization-color]]
|
||||
[:on-press [:maybe fn?]]
|
||||
[:title-icon [:maybe :keyword]]
|
||||
[:account-props {:no-optional true}
|
||||
[:map
|
||||
[:name :string]
|
||||
[:address :string]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
(ns quo.components.list-items.account-list-card.schema)
|
||||
|
||||
(def ^:private ?base
|
||||
[:map
|
||||
[:action {:optional true} [:enum :icon :none]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:account-props
|
||||
[:schema.common/map {:optional true}
|
||||
[:action [:enum :icon :none]]
|
||||
[:blur? [:maybe :boolean]]
|
||||
[:on-press [:maybe fn?]]
|
||||
[:account-props {:no-optional true}
|
||||
[:map {:closed true}
|
||||
[:type [:enum :default :watch-only]]
|
||||
[:name :string]
|
||||
|
@ -13,7 +13,7 @@
|
|||
[:emoji :string]
|
||||
[:size {:optional true} [:enum 80 :size-64 48 32 28 24 20 16]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]
|
||||
[:networks {:optional true} [:* [:map [:network-name :keyword] [:short-name :string]]]]])
|
||||
[:networks [:* [:map [:network-name :keyword] [:short-name :string]]]]])
|
||||
|
||||
(def ^:private ?on-option-press
|
||||
[:map
|
||||
|
|
|
@ -13,20 +13,20 @@
|
|||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:default-active {:optional true} [:maybe [:or :int :keyword]]]
|
||||
[:active-tab-id {:optional true} [:maybe [:or :int :keyword]]]
|
||||
[:data ?data]
|
||||
[:fade-end-percentage {:optional true} [:or :double :string]]
|
||||
[:fade-end? {:optional true} [:maybe :boolean]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:on-change {:optional true} [:maybe fn?]]
|
||||
[:on-scroll {:optional true} [:maybe fn?]]
|
||||
[:scroll-on-press? {:optional true} [:maybe :boolean]]
|
||||
[:scrollable? {:optional true} [:maybe :boolean]]
|
||||
[:style {:optional true} [:maybe :map]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:size {:optional true} [:maybe [:or :keyword :int]]]
|
||||
[:in-scroll-view? {:optional true} [:maybe :boolean]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]]
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:default-active [:or :int :keyword]]
|
||||
[:active-tab-id [:or :int :keyword]]
|
||||
[:data {:no-maybe true} ?data]
|
||||
[:fade-end-percentage {:no-maybe true} [:or :double :string]]
|
||||
[:fade-end? :boolean]
|
||||
[:blur? :boolean]
|
||||
[:on-change fn?]
|
||||
[:on-scroll fn?]
|
||||
[:scroll-on-press? :boolean]
|
||||
[:scrollable? :boolean]
|
||||
[:style :map]
|
||||
[:container-style :map]
|
||||
[:size [:or :keyword :int]]
|
||||
[:in-scroll-view? :boolean]
|
||||
[:customization-color :schema.common/customization-color]]]]
|
||||
:any])
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:options {:optional true} [:maybe [:enum :add :hold]]]
|
||||
[:size {:optional true} [:maybe [:enum :size-24 :size-32]]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:collectible-img-src :schema.common/image-source]
|
||||
[:collectible-name :string]
|
||||
[:collectible-id {:optional true} [:maybe :string]]]]]
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:options [:enum :add :hold]]
|
||||
[:size [:enum :size-24 :size-32]]
|
||||
[:blur? :boolean]
|
||||
[:collectible-id :string]
|
||||
[:collectible-img-src {:no-optional true :no-maybe true}
|
||||
:schema.common/image-source]
|
||||
[:collectible-name {:no-optional true :no-maybe true}
|
||||
:string]]]]
|
||||
:any])
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
(ns quo.components.wallet.account-card.schema)
|
||||
|
||||
(def ^:private ?base
|
||||
[:map
|
||||
[:type {:optional true} [:enum :default :watch-only :add-account :empty :missing-keypair]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:metrics? {:optional true} [:maybe :boolean]]
|
||||
[:on-press {:optional true} [:maybe fn?]]])
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:type {:no-maybe true} [:enum :default :watch-only :add-account :empty :missing-keypair]]
|
||||
[:customization-color :schema.common/customization-color]
|
||||
[:metrics? :boolean]
|
||||
[:on-press fn?]])
|
||||
|
||||
(def ^:private ?amount
|
||||
[:map
|
||||
[:amount {:optional true} [:maybe :string]]])
|
||||
|
||||
(def ^:private ?card
|
||||
[:map
|
||||
[:balance {:optional true} [:maybe :string]]
|
||||
[:loading? {:optional true} [:maybe :boolean]]
|
||||
[:name {:optional true} [:maybe :string]]
|
||||
[:percentage-value {:optional true} [:maybe :string]]
|
||||
[:emoji {:optional true} [:maybe :string]]])
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:balance :string]
|
||||
[:loading? :boolean]
|
||||
[:name :string]
|
||||
[:percentage-value :string]
|
||||
[:emoji :string]])
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
[:keypair-name {:optional true} [:maybe :string]]])
|
||||
|
||||
(def ^:private ?default-keypair
|
||||
[:map
|
||||
[:profile-picture {:optional true} [:maybe :schema.common/image-source]]
|
||||
[:derivation-path {:optional true} [:maybe :string]]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]])
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:profile-picture :schema.common/image-source]
|
||||
[:derivation-path :string]
|
||||
[:on-press fn?]
|
||||
[:customization-color :schema.common/customization-color]])
|
||||
|
||||
(def ^:private ?recovery-phrase
|
||||
[:map
|
||||
|
|
|
@ -4,15 +4,14 @@
|
|||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:address {:optional true} [:maybe :string]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:format {:optional true} [:enum :short :long]]
|
||||
[:networks {:optional true}
|
||||
[:maybe [:sequential [:map [:network-name :keyword] [:short-name :string]]]]]
|
||||
[:full-address? {:optional true} [:maybe :boolean]]
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:address :string]
|
||||
[:blur? :boolean]
|
||||
[:format {:no-maybe true} [:enum :short :long]]
|
||||
[:networks [:sequential [:map [:network-name :keyword] [:short-name :string]]]]
|
||||
[:full-address? :boolean]
|
||||
;; TODO: size and weight are text schemas and should be imported here
|
||||
;; https://github.com/status-im/status-mobile/issues/19443
|
||||
[:size {:optional true} [:maybe :keyword]]
|
||||
[:weight {:optional true} [:maybe :keyword]]]]]
|
||||
[:size :keyword]
|
||||
[:weight :keyword]]]]
|
||||
:any])
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:status {:optional true} [:maybe [:enum :default :error]]]
|
||||
[:on-inc-press {:optional true} [:maybe fn?]]
|
||||
[:on-dec-press {:optional true} [:maybe fn?]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:min-value {:optional true} [:maybe :int]]
|
||||
[:max-value {:optional true} [:maybe :int]]
|
||||
[:value [:maybe :int]]]]]
|
||||
[:schema.common/map {:closed true :optional true :maybe true}
|
||||
[:status [:enum :default :error]]
|
||||
[:on-inc-press fn?]
|
||||
[:on-dec-press fn?]
|
||||
[:container-style :map]
|
||||
[:min-value :int]
|
||||
[:max-value :int]
|
||||
[:value {:no-optional true} :int]]]]
|
||||
:any])
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:type [:enum :token :collectible]]
|
||||
[:amount {:optional true} [:maybe [:or :string :int]]]
|
||||
[:token {:optional true} [:maybe :string]]
|
||||
[:token-img-src {:optional true} [:maybe :schema.common/image-source]]
|
||||
[:collectible-img-src {:optional true} [:maybe :schema.common/image-source]]
|
||||
[:collectible-name {:optional true} [:maybe :string]]
|
||||
[:divider? {:optional true} [:maybe :boolean]]
|
||||
[:container-style {:optional true} [:maybe :map]]]]]
|
||||
[:schema.common/map {:closed true :optional true :maybe true}
|
||||
[:type {:no-maybe true} [:enum :token :collectible]]
|
||||
[:amount [:or :string :int]]
|
||||
[:token :string]
|
||||
[:token-img-src :schema.common/image-source]
|
||||
[:collectible-img-src :schema.common/image-source]
|
||||
[:collectible-name :string]
|
||||
[:divider? :boolean]
|
||||
[:container-style :map]]]]
|
||||
:any])
|
||||
|
|
|
@ -5,18 +5,18 @@
|
|||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:transaction {:optional true} [:maybe [:enum :send :swap :bridge]]]
|
||||
[:first-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
||||
[:second-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
||||
[:third-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
||||
[:fourth-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
||||
[:fifth-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
||||
[:second-tag-prefix {:optional true} [:maybe :keyword]]
|
||||
[:third-tag-prefix {:optional true} [:maybe :keyword]]
|
||||
[:fourth-tag-prefix {:optional true} [:maybe :keyword]]
|
||||
[:max-fees {:optional true} [:maybe :string]]
|
||||
[:nonce {:optional true} [:maybe :int]]
|
||||
[:input-data {:optional true} [:maybe :string]]
|
||||
[:on-press {:optional true} [:maybe fn?]]]]]
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:transaction [:enum :send :swap :bridge]]
|
||||
[:first-tag context-tag-schema/?schema]
|
||||
[:second-tag context-tag-schema/?schema]
|
||||
[:third-tag context-tag-schema/?schema]
|
||||
[:fourth-tag context-tag-schema/?schema]
|
||||
[:fifth-tag context-tag-schema/?schema]
|
||||
[:second-tag-prefix :keyword]
|
||||
[:third-tag-prefix :keyword]
|
||||
[:fourth-tag-prefix :keyword]
|
||||
[:max-fees :string]
|
||||
[:nonce :int]
|
||||
[:input-data :string]
|
||||
[:on-press fn?]]]]
|
||||
:any])
|
||||
|
|
|
@ -1,7 +1,89 @@
|
|||
(ns schema.common
|
||||
(:require
|
||||
[malli.core :as malli]
|
||||
malli.util
|
||||
[schema.registry :as registry]))
|
||||
|
||||
(defn- optional-keys
|
||||
"Makes map keys optional, non-recursively.
|
||||
|
||||
Ignores keys with schema property :no-maybe true."
|
||||
[?schema]
|
||||
(let [mapper (fn [[_k properties :as entry]]
|
||||
(if (:no-optional properties)
|
||||
(update entry 1 dissoc :no-optional)
|
||||
(update entry 1 assoc :optional true)))]
|
||||
(malli.util/transform-entries ?schema #(map mapper %) nil)))
|
||||
|
||||
(defn- maybe-keys
|
||||
"Makes map keys nullable, non-recursively.
|
||||
|
||||
Ignores keys with schema property :no-maybe true."
|
||||
[?schema]
|
||||
(let [mapper (fn [[_k properties ?key :as entry]]
|
||||
(let [key-form (malli/form ?key)]
|
||||
(if (or (:no-maybe properties)
|
||||
(and (vector? key-form)
|
||||
(= :maybe (first key-form))))
|
||||
(update entry 1 dissoc :no-maybe)
|
||||
(assoc entry 2 [:maybe key-form]))))]
|
||||
(malli.util/transform-entries ?schema #(map mapper %) nil)))
|
||||
|
||||
(defn- ?map-optional-maybe
|
||||
"This implementation should closely track how the base schema `:map` is
|
||||
implemented by malli. This is a solution to sort of inherit a base schema and
|
||||
reuse its implementation, but extend it to support new features.
|
||||
|
||||
Usage:
|
||||
|
||||
[:schema.common/map {:optional true :maybe true}
|
||||
[:type [:enum :default :multiuser :group]]
|
||||
[:customization-color :schema.common/customization-color]
|
||||
[:blur? boolean?]
|
||||
[:value {:no-optional true} pos-int?]]
|
||||
|
||||
This is the same as if you manually entered the following:
|
||||
|
||||
[:map
|
||||
[:type {:optional true} [:maybe [:enum :default :multiuser :group]]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:value [:maybe pos-int?]]]
|
||||
|
||||
You can verify the final transformed `:schema.common/map` by
|
||||
calling `(malli.core/form ?some-schema)`.
|
||||
|
||||
Schema `:schema.common/map` may take two properties:
|
||||
|
||||
- When `:optional` is non-nil, every key will have its `:optional` property
|
||||
set to true. If any key uses the property `:no-optional` non-nil, the key is
|
||||
ignored.
|
||||
|
||||
- When `:maybe` is non-nil, every key will have its children wrapped by a
|
||||
`:maybe` schema. If any key uses the property `:no-maybe` non-nil, the key is
|
||||
ignored.
|
||||
"
|
||||
[]
|
||||
^{:type ::malli/into-schema}
|
||||
(reify
|
||||
malli/AST
|
||||
(-from-ast [parent ast options]
|
||||
(malli/-from-ast parent ast options))
|
||||
|
||||
malli/IntoSchema
|
||||
(-type [_]
|
||||
:schema.common/map)
|
||||
(-type-properties [this]
|
||||
(malli/-type-properties this))
|
||||
(-properties-schema [this options]
|
||||
(malli/-properties-schema this options))
|
||||
(-children-schema [this options]
|
||||
(malli/-children-schema this options))
|
||||
(-into-schema [_parent props children options]
|
||||
(cond-> (malli/into-schema :map (dissoc props :optional :maybe) children options)
|
||||
(:optional props) (optional-keys)
|
||||
(:maybe props) (maybe-keys)))))
|
||||
|
||||
(def ^:private ?theme
|
||||
[:enum :light :dark])
|
||||
|
||||
|
@ -44,4 +126,5 @@
|
|||
(registry/register ::image-source ?image-source)
|
||||
(registry/register ::rpc-call ?rpc-call)
|
||||
(registry/register ::exception ?exception)
|
||||
(registry/register ::map (?map-optional-maybe))
|
||||
(registry/register ::hiccup ?hiccup))
|
||||
|
|
|
@ -17,7 +17,13 @@
|
|||
We normalize `?schema` by always registering it as a proper instance of
|
||||
`malli.core/Schema` to avoid inconsistencies down the road."
|
||||
[type ?schema]
|
||||
(swap! registry assoc type (malli/schema ?schema))
|
||||
(swap! registry assoc
|
||||
type
|
||||
;; An into-schema instance should not be converted to schema. This will cause a
|
||||
;; :malli.core/invalid-schema. One such schema is `:schema.common/map`.
|
||||
(if (malli/into-schema? ?schema)
|
||||
?schema
|
||||
(malli/schema ?schema)))
|
||||
?schema)
|
||||
|
||||
(defn merge
|
||||
|
|
Loading…
Reference in New Issue