chore(malli)_: New map schema to reduce optional/maybe verbosity
This commit is contained in:
parent
a92b50afea
commit
8df314b2c2
|
@ -6,15 +6,13 @@
|
||||||
[:=>
|
[:=>
|
||||||
[:catn
|
[:catn
|
||||||
[:props
|
[:props
|
||||||
[:map
|
[:schema.common/map {:optional true :maybe true}
|
||||||
[:full-name {:optional true} [:maybe string?]]
|
[:full-name string?]
|
||||||
[:size {:optional true} [:maybe (into [:enum] (keys style/sizes))]]
|
[:size (into [:enum] (keys style/sizes))]
|
||||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
[:customization-color :schema.common/customization-color]
|
||||||
[:static? {:optional true} [:maybe boolean?]]
|
[:static? boolean?]
|
||||||
[:status-indicator? {:optional true} [:maybe boolean?]]
|
[:status-indicator? boolean?]
|
||||||
[:online? {:optional true} [:maybe boolean?]]
|
[:online? boolean?]
|
||||||
[:ring? {:optional true} [:maybe boolean?]]
|
[:ring? boolean?]
|
||||||
[:profile-picture
|
[:profile-picture :schema.quo/profile-picture-source]]]]
|
||||||
{:optional true}
|
|
||||||
[:maybe :schema.quo/profile-picture-source]]]]]
|
|
||||||
:any])
|
:any])
|
||||||
|
|
|
@ -3,17 +3,16 @@
|
||||||
(def ?schema
|
(def ?schema
|
||||||
[:=>
|
[:=>
|
||||||
[:cat
|
[:cat
|
||||||
[:map {:closed true}
|
[:schema.common/map {:closed true :optional true :maybe true}
|
||||||
[:accessibility-label {:optional true} [:maybe :keyword]]
|
[:accessibility-label :keyword]
|
||||||
[:type {:optional true} [:maybe [:enum :main :danger]]]
|
[:type [:enum :main :danger]]
|
||||||
[:action {:optional true} [:maybe [:enum :arrow :toggle :input]]]
|
[:action [:enum :arrow :toggle :input]]
|
||||||
[:icon {:optional true} [:maybe :keyword]]
|
[:icon :keyword]
|
||||||
[:description {:optional true} [:maybe :string]]
|
[:description :string]
|
||||||
[:state {:optional true} [:maybe [:enum :selected]]]
|
[:state [:enum :selected]]
|
||||||
[:title {:optional true} :string]
|
[:title {:no-maybe true} :string]
|
||||||
[:on-press {:optional true} [:maybe fn?]]
|
[:on-press fn?]
|
||||||
[:input-props {:optional true} [:maybe :map]]
|
[:input-props :map]
|
||||||
[:customization-color {:optional true}
|
[:customization-color :schema.common/customization-color]
|
||||||
[:maybe :schema.common/customization-color]]
|
[:blur? :boolean]]]
|
||||||
[:blur? {:optional true} [:maybe :boolean]]]]
|
|
||||||
:any])
|
:any])
|
||||||
|
|
|
@ -20,15 +20,14 @@
|
||||||
[:on-options-press {:optional true} [:maybe fn?]]])
|
[:on-options-press {:optional true} [:maybe fn?]]])
|
||||||
|
|
||||||
(def ^:private ?base
|
(def ^:private ?base
|
||||||
[:map
|
[:schema.common/map {:optional true}
|
||||||
[:type {:optional true}
|
[:type [:enum :default :tag :action :balance-neutral :balance-negative :balance-positive]]
|
||||||
[:enum :default :tag :action :balance-neutral :balance-negative :balance-positive]]
|
[:state [:enum :default :selected :active]]
|
||||||
[:state {:optional true} [:enum :default :selected :active]]
|
[:blur? [:maybe :boolean]]
|
||||||
[:blur? {:optional true} [:maybe :boolean]]
|
[:customization-color [:maybe :schema.common/customization-color]]
|
||||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
[:on-press [:maybe fn?]]
|
||||||
[:on-press {:optional true} [:maybe fn?]]
|
[:title-icon [:maybe :keyword]]
|
||||||
[:title-icon {:optional true} [:maybe :keyword]]
|
[:account-props {:no-optional true}
|
||||||
[:account-props
|
|
||||||
[:map
|
[:map
|
||||||
[:name :string]
|
[:name :string]
|
||||||
[:address :string]
|
[:address :string]
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
(ns quo.components.list-items.account-list-card.schema)
|
(ns quo.components.list-items.account-list-card.schema)
|
||||||
|
|
||||||
(def ^:private ?base
|
(def ^:private ?base
|
||||||
[:map
|
[:schema.common/map {:optional true}
|
||||||
[:action {:optional true} [:enum :icon :none]]
|
[:action [:enum :icon :none]]
|
||||||
[:blur? {:optional true} [:maybe :boolean]]
|
[:blur? [:maybe :boolean]]
|
||||||
[:on-press {:optional true} [:maybe fn?]]
|
[:on-press [:maybe fn?]]
|
||||||
[:account-props
|
[:account-props {:no-optional true}
|
||||||
[:map {:closed true}
|
[:map {:closed true}
|
||||||
[:type [:enum :default :watch-only]]
|
[:type [:enum :default :watch-only]]
|
||||||
[:name :string]
|
[:name :string]
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
[:emoji :string]
|
[:emoji :string]
|
||||||
[:size {:optional true} [:enum 80 :size-64 48 32 28 24 20 16]]
|
[:size {:optional true} [:enum 80 :size-64 48 32 28 24 20 16]]
|
||||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]
|
[: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
|
(def ^:private ?on-option-press
|
||||||
[:map
|
[:map
|
||||||
|
|
|
@ -13,20 +13,20 @@
|
||||||
[:=>
|
[:=>
|
||||||
[:catn
|
[:catn
|
||||||
[:props
|
[:props
|
||||||
[:map
|
[:schema.common/map {:optional true :maybe true}
|
||||||
[:default-active {:optional true} [:maybe [:or :int :keyword]]]
|
[:default-active [:or :int :keyword]]
|
||||||
[:active-tab-id {:optional true} [:maybe [:or :int :keyword]]]
|
[:active-tab-id [:or :int :keyword]]
|
||||||
[:data ?data]
|
[:data {:no-maybe true} ?data]
|
||||||
[:fade-end-percentage {:optional true} [:or :double :string]]
|
[:fade-end-percentage {:no-maybe true} [:or :double :string]]
|
||||||
[:fade-end? {:optional true} [:maybe :boolean]]
|
[:fade-end? :boolean]
|
||||||
[:blur? {:optional true} [:maybe :boolean]]
|
[:blur? :boolean]
|
||||||
[:on-change {:optional true} [:maybe fn?]]
|
[:on-change fn?]
|
||||||
[:on-scroll {:optional true} [:maybe fn?]]
|
[:on-scroll fn?]
|
||||||
[:scroll-on-press? {:optional true} [:maybe :boolean]]
|
[:scroll-on-press? :boolean]
|
||||||
[:scrollable? {:optional true} [:maybe :boolean]]
|
[:scrollable? :boolean]
|
||||||
[:style {:optional true} [:maybe :map]]
|
[:style :map]
|
||||||
[:container-style {:optional true} [:maybe :map]]
|
[:container-style :map]
|
||||||
[:size {:optional true} [:maybe [:or :keyword :int]]]
|
[:size [:or :keyword :int]]
|
||||||
[:in-scroll-view? {:optional true} [:maybe :boolean]]
|
[:in-scroll-view? :boolean]
|
||||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]]
|
[:customization-color :schema.common/customization-color]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
|
@ -4,11 +4,13 @@
|
||||||
[:=>
|
[:=>
|
||||||
[:catn
|
[:catn
|
||||||
[:props
|
[:props
|
||||||
[:map
|
[:schema.common/map {:optional true :maybe true}
|
||||||
[:options {:optional true} [:maybe [:enum :add :hold]]]
|
[:options [:enum :add :hold]]
|
||||||
[:size {:optional true} [:maybe [:enum :size-24 :size-32]]]
|
[:size [:enum :size-24 :size-32]]
|
||||||
[:blur? {:optional true} [:maybe :boolean]]
|
[:blur? :boolean]
|
||||||
[:collectible-img-src :schema.common/image-source]
|
[:collectible-id :string]
|
||||||
[:collectible-name :string]
|
[:collectible-img-src {:no-optional true :no-maybe true}
|
||||||
[:collectible-id {:optional true} [:maybe :string]]]]]
|
:schema.common/image-source]
|
||||||
|
[:collectible-name {:no-optional true :no-maybe true}
|
||||||
|
:string]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
(ns quo.components.wallet.account-card.schema)
|
(ns quo.components.wallet.account-card.schema)
|
||||||
|
|
||||||
(def ^:private ?base
|
(def ^:private ?base
|
||||||
[:map
|
[:schema.common/map {:optional true :maybe true}
|
||||||
[:type {:optional true} [:enum :default :watch-only :add-account :empty :missing-keypair]]
|
[:type {:no-maybe true} [:enum :default :watch-only :add-account :empty :missing-keypair]]
|
||||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
[:customization-color :schema.common/customization-color]
|
||||||
[:metrics? {:optional true} [:maybe :boolean]]
|
[:metrics? :boolean]
|
||||||
[:on-press {:optional true} [:maybe fn?]]])
|
[:on-press fn?]])
|
||||||
|
|
||||||
(def ^:private ?amount
|
(def ^:private ?amount
|
||||||
[:map
|
[:map
|
||||||
[:amount {:optional true} [:maybe :string]]])
|
[:amount {:optional true} [:maybe :string]]])
|
||||||
|
|
||||||
(def ^:private ?card
|
(def ^:private ?card
|
||||||
[:map
|
[:schema.common/map {:optional true :maybe true}
|
||||||
[:balance {:optional true} [:maybe :string]]
|
[:balance :string]
|
||||||
[:loading? {:optional true} [:maybe :boolean]]
|
[:loading? :boolean]
|
||||||
[:name {:optional true} [:maybe :string]]
|
[:name :string]
|
||||||
[:percentage-value {:optional true} [:maybe :string]]
|
[:percentage-value :string]
|
||||||
[:emoji {:optional true} [:maybe :string]]])
|
[:emoji :string]])
|
||||||
|
|
||||||
(def ?schema
|
(def ?schema
|
||||||
[:=>
|
[:=>
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
[:keypair-name {:optional true} [:maybe :string]]])
|
[:keypair-name {:optional true} [:maybe :string]]])
|
||||||
|
|
||||||
(def ^:private ?default-keypair
|
(def ^:private ?default-keypair
|
||||||
[:map
|
[:schema.common/map {:optional true :maybe true}
|
||||||
[:profile-picture {:optional true} [:maybe :schema.common/image-source]]
|
[:profile-picture :schema.common/image-source]
|
||||||
[:derivation-path {:optional true} [:maybe :string]]
|
[:derivation-path :string]
|
||||||
[:on-press {:optional true} [:maybe fn?]]
|
[:on-press fn?]
|
||||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]])
|
[:customization-color :schema.common/customization-color]])
|
||||||
|
|
||||||
(def ^:private ?recovery-phrase
|
(def ^:private ?recovery-phrase
|
||||||
[:map
|
[:map
|
||||||
|
|
|
@ -4,15 +4,14 @@
|
||||||
[:=>
|
[:=>
|
||||||
[:catn
|
[:catn
|
||||||
[:props
|
[:props
|
||||||
[:map
|
[:schema.common/map {:optional true :maybe true}
|
||||||
[:address {:optional true} [:maybe :string]]
|
[:address :string]
|
||||||
[:blur? {:optional true} [:maybe :boolean]]
|
[:blur? :boolean]
|
||||||
[:format {:optional true} [:enum :short :long]]
|
[:format {:no-maybe true} [:enum :short :long]]
|
||||||
[:networks {:optional true}
|
[:networks [:sequential [:map [:network-name :keyword] [:short-name :string]]]]
|
||||||
[:maybe [:sequential [:map [:network-name :keyword] [:short-name :string]]]]]
|
[:full-address? :boolean]
|
||||||
[:full-address? {:optional true} [:maybe :boolean]]
|
|
||||||
;; TODO: size and weight are text schemas and should be imported here
|
;; TODO: size and weight are text schemas and should be imported here
|
||||||
;; https://github.com/status-im/status-mobile/issues/19443
|
;; https://github.com/status-im/status-mobile/issues/19443
|
||||||
[:size {:optional true} [:maybe :keyword]]
|
[:size :keyword]
|
||||||
[:weight {:optional true} [:maybe :keyword]]]]]
|
[:weight :keyword]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
[:=>
|
[:=>
|
||||||
[:catn
|
[:catn
|
||||||
[:props
|
[:props
|
||||||
[:map {:closed true}
|
[:schema.common/map {:closed true :optional true :maybe true}
|
||||||
[:status {:optional true} [:maybe [:enum :default :error]]]
|
[:status [:enum :default :error]]
|
||||||
[:on-inc-press {:optional true} [:maybe fn?]]
|
[:on-inc-press fn?]
|
||||||
[:on-dec-press {:optional true} [:maybe fn?]]
|
[:on-dec-press fn?]
|
||||||
[:container-style {:optional true} [:maybe :map]]
|
[:container-style :map]
|
||||||
[:min-value {:optional true} [:maybe :int]]
|
[:min-value :int]
|
||||||
[:max-value {:optional true} [:maybe :int]]
|
[:max-value :int]
|
||||||
[:value [:maybe :int]]]]]
|
[:value {:no-optional true} :int]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
[:=>
|
[:=>
|
||||||
[:catn
|
[:catn
|
||||||
[:props
|
[:props
|
||||||
[:map {:closed true}
|
[:schema.common/map {:closed true :optional true :maybe true}
|
||||||
[:type [:enum :token :collectible]]
|
[:type {:no-maybe true} [:enum :token :collectible]]
|
||||||
[:amount {:optional true} [:maybe [:or :string :int]]]
|
[:amount [:or :string :int]]
|
||||||
[:token {:optional true} [:maybe :string]]
|
[:token :string]
|
||||||
[:token-img-src {:optional true} [:maybe :schema.common/image-source]]
|
[:token-img-src :schema.common/image-source]
|
||||||
[:collectible-img-src {:optional true} [:maybe :schema.common/image-source]]
|
[:collectible-img-src :schema.common/image-source]
|
||||||
[:collectible-name {:optional true} [:maybe :string]]
|
[:collectible-name :string]
|
||||||
[:divider? {:optional true} [:maybe :boolean]]
|
[:divider? :boolean]
|
||||||
[:container-style {:optional true} [:maybe :map]]]]]
|
[:container-style :map]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
|
@ -5,18 +5,18 @@
|
||||||
[:=>
|
[:=>
|
||||||
[:catn
|
[:catn
|
||||||
[:props
|
[:props
|
||||||
[:map
|
[:schema.common/map {:optional true :maybe true}
|
||||||
[:transaction {:optional true} [:maybe [:enum :send :swap :bridge]]]
|
[:transaction [:enum :send :swap :bridge]]
|
||||||
[:first-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
[:first-tag context-tag-schema/?schema]
|
||||||
[:second-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
[:second-tag context-tag-schema/?schema]
|
||||||
[:third-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
[:third-tag context-tag-schema/?schema]
|
||||||
[:fourth-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
[:fourth-tag context-tag-schema/?schema]
|
||||||
[:fifth-tag {:optional true} [:maybe context-tag-schema/?schema]]
|
[:fifth-tag context-tag-schema/?schema]
|
||||||
[:second-tag-prefix {:optional true} [:maybe :keyword]]
|
[:second-tag-prefix :keyword]
|
||||||
[:third-tag-prefix {:optional true} [:maybe :keyword]]
|
[:third-tag-prefix :keyword]
|
||||||
[:fourth-tag-prefix {:optional true} [:maybe :keyword]]
|
[:fourth-tag-prefix :keyword]
|
||||||
[:max-fees {:optional true} [:maybe :string]]
|
[:max-fees :string]
|
||||||
[:nonce {:optional true} [:maybe :int]]
|
[:nonce :int]
|
||||||
[:input-data {:optional true} [:maybe :string]]
|
[:input-data :string]
|
||||||
[:on-press {:optional true} [:maybe fn?]]]]]
|
[:on-press fn?]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
|
@ -1,7 +1,89 @@
|
||||||
(ns schema.common
|
(ns schema.common
|
||||||
(:require
|
(:require
|
||||||
|
[malli.core :as malli]
|
||||||
|
malli.util
|
||||||
[schema.registry :as registry]))
|
[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
|
(def ^:private ?theme
|
||||||
[:enum :light :dark])
|
[:enum :light :dark])
|
||||||
|
|
||||||
|
@ -44,4 +126,5 @@
|
||||||
(registry/register ::image-source ?image-source)
|
(registry/register ::image-source ?image-source)
|
||||||
(registry/register ::rpc-call ?rpc-call)
|
(registry/register ::rpc-call ?rpc-call)
|
||||||
(registry/register ::exception ?exception)
|
(registry/register ::exception ?exception)
|
||||||
|
(registry/register ::map (?map-optional-maybe))
|
||||||
(registry/register ::hiccup ?hiccup))
|
(registry/register ::hiccup ?hiccup))
|
||||||
|
|
|
@ -17,7 +17,13 @@
|
||||||
We normalize `?schema` by always registering it as a proper instance of
|
We normalize `?schema` by always registering it as a proper instance of
|
||||||
`malli.core/Schema` to avoid inconsistencies down the road."
|
`malli.core/Schema` to avoid inconsistencies down the road."
|
||||||
[type ?schema]
|
[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)
|
?schema)
|
||||||
|
|
||||||
(defn merge
|
(defn merge
|
||||||
|
|
Loading…
Reference in New Issue