Add general improvement to openapi and js-like doc output

This commit is contained in:
Andrey Antukh
2025-08-19 14:09:07 +02:00
parent 2b83d0d0e9
commit b472a8ab19
15 changed files with 550 additions and 466 deletions

View File

@@ -18,6 +18,7 @@
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.schema.desc-js-like :as smdj] [app.common.schema.desc-js-like :as smdj]
[app.common.schema.desc-native :as smdn] [app.common.schema.desc-native :as smdn]
[app.common.schema.openapi :as oapi]
[app.common.schema.generators :as sg] [app.common.schema.generators :as sg]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.json :as json] [app.common.json :as json]

View File

@@ -37,14 +37,13 @@
(def ^:private (def ^:private
schema:get-font-variants schema:get-font-variants
[:schema {:title "get-font-variants"} [:and
[:and [:map {:title "get-font-variants"}
[:map [:team-id {:optional true} ::sm/uuid]
[:team-id {:optional true} ::sm/uuid] [:file-id {:optional true} ::sm/uuid]
[:file-id {:optional true} ::sm/uuid] [:project-id {:optional true} ::sm/uuid]
[:project-id {:optional true} ::sm/uuid] [:share-id {:optional true} ::sm/uuid]]
[:share-id {:optional true} ::sm/uuid]] [::sm/contains-any #{:team-id :file-id :project-id}]])
[::sm/contains-any #{:team-id :file-id :project-id}]]])
(sv/defmethod ::get-font-variants (sv/defmethod ::get-font-variants
{::doc/added "1.18" {::doc/added "1.18"

View File

@@ -166,9 +166,6 @@
:servers [{:url (str/ffmt "%/api/rpc" (cf/get :public-uri)) :servers [{:url (str/ffmt "%/api/rpc" (cf/get :public-uri))
;; :description "penpot backend" ;; :description "penpot backend"
}] }]
:security
{:api_key []}
:paths paths :paths paths
:components {:schemas @definitions}})) :components {:schemas @definitions}}))

View File

@@ -83,24 +83,25 @@
[:multi {:decode/json #(update % :grid-type keyword) [:multi {:decode/json #(update % :grid-type keyword)
:gen/gen gen :gen/gen gen
:title "SetDefaultGridChange"
:dispatch :grid-type :dispatch :grid-type
::smd/simplified true} ::smd/simplified true}
[:square [:square
[:map [:map {:title "SetDefautSquareGridAttrs"}
[:type [:= :set-default-grid]] [:type [:= :set-default-grid]]
[:page-id ::sm/uuid] [:page-id ::sm/uuid]
[:grid-type [:= :square]] [:grid-type [:= :square]]
[:params [:maybe ctg/schema:square-params]]]] [:params [:maybe ctg/schema:square-params]]]]
[:column [:column
[:map [:map {:title "SetDefaultColumnGridAttrs"}
[:type [:= :set-default-grid]] [:type [:= :set-default-grid]]
[:page-id ::sm/uuid] [:page-id ::sm/uuid]
[:grid-type [:= :column]] [:grid-type [:= :column]]
[:params [:maybe ctg/schema:column-params]]]] [:params [:maybe ctg/schema:column-params]]]]
[:row [:row
[:map [:map {:title "SetDefaultRowGridAttrs"}
[:type [:= :set-default-grid]] [:type [:= :set-default-grid]]
[:page-id ::sm/uuid] [:page-id ::sm/uuid]
[:grid-type [:= :row]] [:grid-type [:= :row]]
@@ -117,7 +118,7 @@
(if (some? (:params change)) (if (some? (:params change))
(update change :params assoc :id (:id change)) (update change :params assoc :id (:id change))
change))))] change))))]
[:schema {:gen/gen gen} schema])) (sm/update-properties schema assoc :gen/gen gen)))
(def schema:set-flow-change (def schema:set-flow-change
(let [schema [:map {:title "SetFlowChange"} (let [schema [:map {:title "SetFlowChange"}
@@ -132,7 +133,7 @@
(update change :params assoc :id (:id change)) (update change :params assoc :id (:id change))
change))))] change))))]
[:schema {:gen/gen gen} schema])) (sm/update-properties schema assoc :gen/gen gen)))
(def schema:set-plugin-data-change (def schema:set-plugin-data-change
(let [types #{:file :page :shape :color :typography :component} (let [types #{:file :page :shape :color :typography :component}
@@ -169,272 +170,266 @@
:else :else
(dissoc change :page-id)))))] (dissoc change :page-id)))))]
[:and (sm/update-properties schema assoc :gen/gen gen) check1]))
[:and {:gen/gen gen} schema check1]))
(def schema:change (def schema:change
[:schema [:multi {:dispatch :type
[:multi {:dispatch :type :title "Change"
:title "Change" :decode/json #(update % :type keyword)
:decode/json #(update % :type keyword) ::smd/simplified true}
::smd/simplified true}
[:set-comment-thread-position [:set-comment-thread-position
[:map [:map {:title "SetCommentThreadPositionChange"}
[:comment-thread-id ::sm/uuid] [:comment-thread-id ::sm/uuid]
[:page-id ::sm/uuid] [:page-id ::sm/uuid]
[:frame-id [:maybe ::sm/uuid]] [:frame-id [:maybe ::sm/uuid]]
[:position [:maybe ::gpt/point]]]] [:position [:maybe ::gpt/point]]]]
[:add-obj [:add-obj
[:map {:title "AddObjChange"} [:map {:title "AddObjChange"}
[:type [:= :add-obj]] [:type [:= :add-obj]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:obj cts/schema:shape] [:obj cts/schema:shape]
[:page-id {:optional true} ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid] [:component-id {:optional true} ::sm/uuid]
[:frame-id ::sm/uuid] [:frame-id ::sm/uuid]
[:parent-id {:optional true} [:maybe ::sm/uuid]] [:parent-id {:optional true} [:maybe ::sm/uuid]]
[:index {:optional true} [:maybe :int]] [:index {:optional true} [:maybe :int]]
[:ignore-touched {:optional true} :boolean]]] [:ignore-touched {:optional true} :boolean]]]
[:mod-obj [:mod-obj
[:map {:title "ModObjChange"} [:map {:title "ModObjChange"}
[:type [:= :mod-obj]] [:type [:= :mod-obj]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:page-id {:optional true} ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid] [:component-id {:optional true} ::sm/uuid]
[:operations [:vector {:gen/max 5} schema:operation]]]] [:operations [:vector {:gen/max 5} schema:operation]]]]
[:del-obj [:del-obj
[:map {:title "DelObjChange"} [:map {:title "DelObjChange"}
[:type [:= :del-obj]] [:type [:= :del-obj]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:page-id {:optional true} ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid] [:component-id {:optional true} ::sm/uuid]
[:ignore-touched {:optional true} :boolean]]] [:ignore-touched {:optional true} :boolean]]]
[:set-guide schema:set-guide-change] [:set-guide schema:set-guide-change]
[:set-flow schema:set-flow-change] [:set-flow schema:set-flow-change]
[:set-default-grid schema:set-default-grid-change] [:set-default-grid schema:set-default-grid-change]
[:fix-obj [:fix-obj
[:map {:title "FixObjChange"} [:map {:title "FixObjChange"}
[:type [:= :fix-obj]] [:type [:= :fix-obj]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:fix {:optional true} :keyword] [:fix {:optional true} :keyword]
[:page-id {:optional true} ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid]]] [:component-id {:optional true} ::sm/uuid]]]
[:mov-objects [:mov-objects
[:map {:title "MovObjectsChange"} [:map {:title "MovObjectsChange"}
[:type [:= :mov-objects]] [:type [:= :mov-objects]]
[:page-id {:optional true} ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid] [:component-id {:optional true} ::sm/uuid]
[:ignore-touched {:optional true} :boolean] [:ignore-touched {:optional true} :boolean]
[:parent-id ::sm/uuid] [:parent-id ::sm/uuid]
[:shapes ::sm/any] [:shapes ::sm/any]
[:index {:optional true} [:maybe :int]] [:index {:optional true} [:maybe :int]]
[:after-shape {:optional true} ::sm/any] [:after-shape {:optional true} ::sm/any]
[:allow-altering-copies {:optional true} :boolean]]] [:allow-altering-copies {:optional true} :boolean]]]
[:reorder-children [:reorder-children
[:map {:title "ReorderChildrenChange"} [:map {:title "ReorderChildrenChange"}
[:type [:= :reorder-children]] [:type [:= :reorder-children]]
[:page-id {:optional true} ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid] [:component-id {:optional true} ::sm/uuid]
[:ignore-touched {:optional true} :boolean] [:ignore-touched {:optional true} :boolean]
[:parent-id ::sm/uuid] [:parent-id ::sm/uuid]
[:shapes ::sm/any]]] [:shapes ::sm/any]]]
[:add-page [:add-page
[:map {:title "AddPageChange"} [:map {:title "AddPageChange"}
[:type [:= :add-page]] [:type [:= :add-page]]
[:id {:optional true} ::sm/uuid] [:id {:optional true} ::sm/uuid]
[:name {:optional true} :string] [:name {:optional true} :string]
[:page {:optional true} ::sm/any]]] [:page {:optional true} ::sm/any]]]
[:mod-page [:mod-page
[:map {:title "ModPageChange"} [:map {:title "ModPageChange"}
[:type [:= :mod-page]] [:type [:= :mod-page]]
[:id ::sm/uuid] [:id ::sm/uuid]
;; All props are optional, background can be nil because is the ;; All props are optional, background can be nil because is the
;; way to remove already set background ;; way to remove already set background
[:background {:optional true} [:maybe ctc/schema:hex-color]] [:background {:optional true} [:maybe ctc/schema:hex-color]]
[:name {:optional true} :string]]] [:name {:optional true} :string]]]
[:set-plugin-data schema:set-plugin-data-change] [:set-plugin-data schema:set-plugin-data-change]
[:del-page [:del-page
[:map {:title "DelPageChange"} [:map {:title "DelPageChange"}
[:type [:= :del-page]] [:type [:= :del-page]]
[:id ::sm/uuid]]] [:id ::sm/uuid]]]
[:mov-page [:mov-page
[:map {:title "MovPageChange"} [:map {:title "MovPageChange"}
[:type [:= :mov-page]] [:type [:= :mov-page]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:index :int]]] [:index :int]]]
[:reg-objects [:reg-objects
[:map {:title "RegObjectsChange"} [:map {:title "RegObjectsChange"}
[:type [:= :reg-objects]] [:type [:= :reg-objects]]
[:page-id {:optional true} ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid] [:component-id {:optional true} ::sm/uuid]
[:shapes [:vector {:gen/max 5} ::sm/uuid]]]] [:shapes [:vector {:gen/max 5} ::sm/uuid]]]]
[:add-color [:add-color
[:map {:title "AddColorChange"} [:map {:title "AddColorChange"}
[:type [:= :add-color]] [:type [:= :add-color]]
[:color ctc/schema:library-color]]] [:color ctc/schema:library-color]]]
[:mod-color [:mod-color
[:map {:title "ModColorChange"} [:map {:title "ModColorChange"}
[:type [:= :mod-color]] [:type [:= :mod-color]]
[:color ctc/schema:library-color]]] [:color ctc/schema:library-color]]]
[:del-color [:del-color
[:map {:title "DelColorChange"} [:map {:title "DelColorChange"}
[:type [:= :del-color]] [:type [:= :del-color]]
[:id ::sm/uuid]]] [:id ::sm/uuid]]]
;; DEPRECATED: remove before 2.3 [:add-media
[:add-recent-color [:map {:title "AddMediaChange"}
[:map {:title "AddRecentColorChange"}]] [:type [:= :add-media]]
[:object ctf/schema:media]]]
[:add-media [:mod-media
[:map {:title "AddMediaChange"} [:map {:title "ModMediaChange"}
[:type [:= :add-media]] [:type [:= :mod-media]]
[:object ctf/schema:media]]] [:object ctf/schema:media]]]
[:mod-media [:del-media
[:map {:title "ModMediaChange"} [:map {:title "DelMediaChange"}
[:type [:= :mod-media]] [:type [:= :del-media]]
[:object ctf/schema:media]]] [:id ::sm/uuid]]]
[:del-media [:add-component
[:map {:title "DelMediaChange"} [:map {:title "AddComponentChange"}
[:type [:= :del-media]] [:type [:= :add-component]]
[:id ::sm/uuid]]] [:id ::sm/uuid]
[:name :string]
[:shapes {:optional true} [:vector {:gen/max 3} ::sm/any]]
[:path {:optional true} :string]
[:main-instance-id ::sm/uuid]
[:main-instance-page ::sm/uuid]]]
[:add-component [:mod-component
[:map {:title "AddComponentChange"} [:map {:title "ModCompoenentChange"}
[:type [:= :add-component]] [:type [:= :mod-component]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] [:shapes {:optional true} [:vector {:gen/max 3} ::sm/any]]
[:shapes {:optional true} [:vector {:gen/max 3} ::sm/any]] [:name {:optional true} :string]
[:path {:optional true} :string] [:variant-id {:optional true} ::sm/uuid]
[:main-instance-id ::sm/uuid] [:variant-properties {:optional true} [:vector ::ctv/variant-property]]]]
[:main-instance-page ::sm/uuid]]]
[:mod-component [:del-component
[:map {:title "ModCompoenentChange"} [:map {:title "DelComponentChange"}
[:type [:= :mod-component]] [:type [:= :del-component]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:shapes {:optional true} [:vector {:gen/max 3} ::sm/any]] ;; when it is an undo of a cut-paste, we need to undo the movement
[:name {:optional true} :string] ;; of the shapes so we need to move them delta
[:variant-id {:optional true} ::sm/uuid] [:delta {:optional true} ::gpt/point]
[:variant-properties {:optional true} [:vector ::ctv/variant-property]]]] [:skip-undelete? {:optional true} :boolean]]]
[:del-component [:restore-component
[:map {:title "DelComponentChange"} [:map {:title "RestoreComponentChange"}
[:type [:= :del-component]] [:type [:= :restore-component]]
[:id ::sm/uuid] [:id ::sm/uuid]
;; when it is an undo of a cut-paste, we need to undo the movement [:page-id ::sm/uuid]]]
;; of the shapes so we need to move them delta
[:delta {:optional true} ::gpt/point]
[:skip-undelete? {:optional true} :boolean]]]
[:restore-component [:purge-component
[:map {:title "RestoreComponentChange"} [:map {:title "PurgeComponentChange"}
[:type [:= :restore-component]] [:type [:= :purge-component]]
[:id ::sm/uuid] [:id ::sm/uuid]]]
[:page-id ::sm/uuid]]]
[:purge-component [:add-typography
[:map {:title "PurgeComponentChange"} [:map {:title "AddTypogrphyChange"}
[:type [:= :purge-component]] [:type [:= :add-typography]]
[:id ::sm/uuid]]] [:typography ::ctt/typography]]]
[:add-typography [:mod-typography
[:map {:title "AddTypogrphyChange"} [:map {:title "ModTypogrphyChange"}
[:type [:= :add-typography]] [:type [:= :mod-typography]]
[:typography ::ctt/typography]]] [:typography ::ctt/typography]]]
[:mod-typography [:del-typography
[:map {:title "ModTypogrphyChange"} [:map {:title "DelTypogrphyChange"}
[:type [:= :mod-typography]] [:type [:= :del-typography]]
[:typography ::ctt/typography]]] [:id ::sm/uuid]]]
[:del-typography [:update-active-token-themes
[:map {:title "DelTypogrphyChange"} [:map {:title "UpdateActiveTokenThemes"}
[:type [:= :del-typography]] [:type [:= :update-active-token-themes]]
[:id ::sm/uuid]]] [:theme-paths [:set :string]]]]
[:update-active-token-themes [:rename-token-set-group
[:map {:title "UpdateActiveTokenThemes"} [:map {:title "RenameTokenSetGroup"}
[:type [:= :update-active-token-themes]] [:type [:= :rename-token-set-group]]
[:theme-paths [:set :string]]]] [:set-group-path [:vector :string]]
[:set-group-fname :string]]]
[:rename-token-set-group [:move-token-set
[:map {:title "RenameTokenSetGroup"} [:map {:title "MoveTokenSet"}
[:type [:= :rename-token-set-group]] [:type [:= :move-token-set]]
[:set-group-path [:vector :string]] [:from-path [:vector :string]]
[:set-group-fname :string]]] [:to-path [:vector :string]]
[:before-path [:maybe [:vector :string]]]
[:before-group [:maybe :boolean]]]]
[:move-token-set [:move-token-set-group
[:map {:title "MoveTokenSet"} [:map {:title "MoveTokenSetGroup"}
[:type [:= :move-token-set]] [:type [:= :move-token-set-group]]
[:from-path [:vector :string]] [:from-path [:vector :string]]
[:to-path [:vector :string]] [:to-path [:vector :string]]
[:before-path [:maybe [:vector :string]]] [:before-path [:maybe [:vector :string]]]
[:before-group [:maybe :boolean]]]] [:before-group [:maybe :boolean]]]]
[:move-token-set-group [:set-token-theme
[:map {:title "MoveTokenSetGroup"} [:map {:title "SetTokenThemeChange"}
[:type [:= :move-token-set-group]] [:type [:= :set-token-theme]]
[:from-path [:vector :string]] [:theme-name :string]
[:to-path [:vector :string]] [:group :string]
[:before-path [:maybe [:vector :string]]] [:theme [:maybe ctob/schema:token-theme-attrs]]]]
[:before-group [:maybe :boolean]]]]
[:set-token-theme [:set-tokens-lib
[:map {:title "SetTokenThemeChange"} [:map {:title "SetTokensLib"}
[:type [:= :set-token-theme]] [:type [:= :set-tokens-lib]]
[:theme-name :string] [:tokens-lib ::sm/any]]]
[:group :string]
[:theme [:maybe ctob/schema:token-theme-attrs]]]]
[:set-tokens-lib [:set-token-set
[:map {:title "SetTokensLib"} [:map {:title "SetTokenSetChange"}
[:type [:= :set-tokens-lib]] [:type [:= :set-token-set]]
[:tokens-lib ::sm/any]]] [:set-name :string]
[:group? :boolean]
[:set-token-set ;; FIXME: we should not pass private types as part of changes
[:map {:title "SetTokenSetChange"} ;; protocol, the changes protocol should reflect a
[:type [:= :set-token-set]] ;; method/protocol for perform surgical operations on file data,
[:set-name :string] ;; this has nothing todo with internal types of a file data
[:group? :boolean] ;; structure.
[:token-set {:gen/gen (sg/generator ctob/schema:token-set)}
[:maybe [:fn ctob/token-set?]]]]]
;; FIXME: we should not pass private types as part of changes [:set-token
;; protocol, the changes protocol should reflect a [:map {:title "SetTokenChange"}
;; method/protocol for perform surgical operations on file data, [:type [:= :set-token]]
;; this has nothing todo with internal types of a file data [:set-name :string]
;; structure. [:token-id ::sm/uuid]
[:token-set {:gen/gen (sg/generator ctob/schema:token-set)} [:token [:maybe ctob/schema:token-attrs]]]]
[:maybe [:fn ctob/token-set?]]]]]
[:set-token [:set-base-font-size
[:map {:title "SetTokenChange"} [:map {:title "ModBaseFontSize"}
[:type [:= :set-token]] [:type [:= :set-base-font-size]]
[:set-name :string] [:base-font-size :string]]]])
[:token-id ::sm/uuid]
[:token [:maybe ctob/schema:token-attrs]]]]
[:set-base-font-size
[:map {:title "ModBaseFontSize"}
[:type [:= :set-base-font-size]]
[:base-font-size :string]]]]])
(def schema:changes (def schema:changes
[:sequential {:gen/max 5 :gen/min 1} schema:change]) [:sequential {:gen/max 5 :gen/min 1} schema:change])
@@ -936,12 +931,6 @@
[data {:keys [id]}] [data {:keys [id]}]
(ctl/delete-color data id)) (ctl/delete-color data id))
;; DEPRECATED: remove before 2.3
(defmethod process-change :add-recent-color
[data _]
data)
;; -- Media ;; -- Media
(defmethod process-change :add-media (defmethod process-change :add-media

View File

@@ -131,34 +131,10 @@
(->> (entries schema) (->> (entries schema)
(into #{} xf:map-key))) (into #{} xf:map-key)))
(defn update-properties
;; (defn key-transformer [s f & args]
;; [& {:as opts}] (let [s (schema s)]
;; (mt/key-transformer opts)) (apply m/-update-properties s f args)))
;; (defn- transform-map-keys
;; [f o]
;; (cond
;; (record? o)
;; (reduce-kv (fn [res k v]
;; (let [k' (f k)]
;; (if (= k k')
;; res
;; (-> res
;; (assoc k' v)
;; (dissoc k)))))
;; o
;; o)
;; (map? o)
;; (persistent!
;; (reduce-kv (fn [res k v]
;; (assoc! res (f k) v))
;; (transient {})
;; o))
;; :else
;; o))
(defn -transform-map-keys (defn -transform-map-keys
([f] ([f]
@@ -679,8 +655,7 @@
identity)] identity)]
{:pred #(contains? options %) {:pred #(contains? options %)
:type-properties :type-properties
{:title "one-of" {:title "enum"
:description "One of the Set"
:gen/gen (sg/elements options) :gen/gen (sg/elements options)
:decode/string decode :decode/string decode
:decode/json decode :decode/json decode
@@ -723,15 +698,14 @@
{:pred pred {:pred pred
:type-properties :type-properties
{:title "int" {:title "integer"
:description "int" :description "integer"
:error/message "expected to be int/long" :error/message "expected to be int/long"
:error/code "errors.invalid-integer" :error/code "errors.invalid-integer"
:gen/gen gen :gen/gen gen
:decode/string parse-long :decode/string parse-long
:decode/json parse-long :decode/json parse-long
::oapi/type "integer" ::oapi/type "integer"}}))})
::oapi/format "int64"}}))})
(defn parse-double (defn parse-double
[v] [v]
@@ -793,8 +767,8 @@
{:pred pred {:pred pred
:type-properties :type-properties
{:title "int" {:title "number"
:description "int" :description "number"
:error/message "expected to be number" :error/message "expected to be number"
:error/code "errors.invalid-number" :error/code "errors.invalid-number"
:gen/gen gen :gen/gen gen
@@ -844,10 +818,7 @@
#(some (fn [prop] #(some (fn [prop]
(contains? % prop)) (contains? % prop))
choices))] choices))]
{:pred pred {:pred pred}))})
:type-properties
{:title "contains any"
:description "contains predicate"}}))})
;; (register! ;; (register!
;; {:type ::inst ;; {:type ::inst
@@ -968,6 +939,7 @@
:type-properties :type-properties
{:title "string" {:title "string"
:description "not whitespace string" :description "not whitespace string"
::oapi/type "string"
:gen/gen (sg/word-string) :gen/gen (sg/word-string)
:error/fn :error/fn
(fn [{:keys [value schema]}] (fn [{:keys [value schema]}]

View File

@@ -91,11 +91,15 @@
(defmethod visit :int [_ schema _ _] (str "integer" (-titled schema) (-min-max-suffix-number schema))) (defmethod visit :int [_ schema _ _] (str "integer" (-titled schema) (-min-max-suffix-number schema)))
(defmethod visit :double [_ schema _ _] (str "double" (-titled schema) (-min-max-suffix-number schema))) (defmethod visit :double [_ schema _ _] (str "double" (-titled schema) (-min-max-suffix-number schema)))
(defmethod visit :select-keys [_ schema _ options] (describe* (m/deref schema) options)) (defmethod visit :select-keys [_ schema _ options] (describe* (m/deref schema) options))
(defmethod visit :and [_ s children _] (str (str/join " && " children) (-titled s))) (defmethod visit :and [_ s children _]
(str (str/join " && " (filter some? children)) (-titled s)))
(defmethod visit :enum [_ s children _options] (str "enum" (-titled s) " of " (str/join ", " children))) (defmethod visit :enum [_ s children _options] (str "enum" (-titled s) " of " (str/join ", " children)))
(defmethod visit :maybe [_ _ children _] (str (first children) " nullable")) (defmethod visit :maybe [_ _ children _] (str (first children) " nullable"))
(defmethod visit :tuple [_ _ children _] (str "(" (str/join ", " children) ")")) (defmethod visit :tuple [_ _ children _] (str "(" (str/join ", " children) ")"))
(defmethod visit :re [_ s _ options] (str "regex pattern " (-titled s) "matching " (pr-str (first (m/children s options))))) (defmethod visit :re [_ _ children _]
(let [pattern (first children)]
(str "string & regex pattern /" (str pattern) "/")))
(defmethod visit :any [_ s _ _] (str "anything" (-titled s))) (defmethod visit :any [_ s _ _] (str "anything" (-titled s)))
(defmethod visit :some [_ _ _ _] "anything but null") (defmethod visit :some [_ _ _ _] "anything but null")
(defmethod visit :nil [_ _ _ _] "null") (defmethod visit :nil [_ _ _ _] "null")
@@ -108,10 +112,11 @@
(defmethod visit :uuid [_ _ _ _] "uuid") (defmethod visit :uuid [_ _ _ _] "uuid")
(defmethod visit :boolean [_ _ _ _] "boolean") (defmethod visit :boolean [_ _ _ _] "boolean")
(defmethod visit :keyword [_ _ _ _] "string") (defmethod visit :keyword [_ _ _ _] "string")
(defmethod visit :fn [_ _ _ _] "FN") (defmethod visit :fn [_ _ _ _]
nil)
(defmethod visit :vector [_ _ children _] (defmethod visit :vector [_ _ children _]
(str "[" (last children) "]")) (str "[" (str/trim (last children)) "]"))
(defn -tagged [children] (map (fn [[tag _ c]] (str c " (tag: " tag ")")) children)) (defn -tagged [children] (map (fn [[tag _ c]] (str c " (tag: " tag ")")) children))
@@ -137,8 +142,15 @@
(some? suffix) (some? suffix)
(str suffix)))) (str suffix))))
(defmethod visit :map-of [_ _ children _] (defmethod visit :map-of
(str "map[" (first children) "," (second children) "]")) [_ schema children _]
(let [props (m/properties schema)
title (some->> (:title props) str/camel str/capital)]
(str (if title
(str "type " title ": ")
"")
"map[" (first children) "," (second children) "]")))
(defmethod visit :union [_ _ children _] (defmethod visit :union [_ _ children _]
(str/join " | " children)) (str/join " | " children))
@@ -156,61 +168,104 @@
(or (:title props) (or (:title props)
"*"))) "*")))
(defn- format-map
[schema children]
(let [props (m/properties schema)
closed? (get props :closed)
title (some->> (:title props) str/camel str/capital)
optional (into #{} (comp (filter (m/-comp :optional second))
(map first))
children)
entries (->> children
(map (fn [[k _ s]]
;; NOTE: maybe we can detect multiple lines
;; and then just insert a break line
(str " " (str/camel k)
(when (contains? optional k) "?")
": " (str/trim s))))
(str/join ",\n"))
header (cond-> (str "type " title)
closed? (str "!")
(some? title) (str " "))]
(str header "{\n" entries "\n}")))
(defmethod visit :map (defmethod visit :map
[_ schema children {:keys [::level ::max-level] :as options}] [_ schema children {:keys [::level] :as options}]
(let [props (m/properties schema) (let [props (m/properties schema)
closed? (:closed props) extracted? (get props ::extracted false)]
title (some->> (:title props) str/camel str/capital)]
(if (>= level max-level) (cond
(or (some-> title str) (or (= level 0) extracted?)
"<untitled>") (format-map schema children)
(let [optional (into #{} (comp (filter (m/-comp :optional second))
(map first))
children)
entries (->> children
(map (fn [[k _ s]]
(str (pad " " level) (str/camel k)
(when (contains? optional k) "?")
": " s)))
(str/join ",\n"))
header (cond-> (str "type " title) :else
closed? (str "!") (let [schema (mu/update-properties schema assoc ::extracted true)
(some? title) (str " "))] title (or (some->> (:title props) str/camel str/capital) "<untitled>")]
(swap! *definitions* conj (format-map schema children))
title))))
(str (pad header level) "{\n" entries "\n" (pad "}\n" level)))))) (defn format-multi
[s children]
(let [props (m/properties s)
title (or (some-> (:title props) str/camel str/capital) "<untitled>")
dispatcher (or (-> s m/properties :dispatch-description)
(-> s m/properties :dispatch))
entries (->> children
(map (fn [[_ _ entry]]
(pad entry 1)))
(str/join ",\n"))
header (str "type " title " [dispatch=" (d/name dispatcher) "]")]
(str header " {\n" entries "\n}")))
(defmethod visit :multi (defmethod visit :multi
[_ s children {:keys [::level ::max-level] :as options}] [_ schema children {:keys [::level] :as options}]
(let [props (m/properties s) (let [props (m/properties schema)
title (some-> (:title props) str/camel str/capital)] title (or (some-> (:title props) str/camel str/capital) "<untitled>")
(if (>= level max-level) extracted? (get props ::extracted false)]
title
(let [dispatcher (or (-> s m/properties :dispatch-description)
(-> s m/properties :dispatch))
prefix (apply str (take (inc level) (repeat " "))) (cond
(or (zero? level) extracted?)
(format-multi schema children)
entries (->> children :else
(map (fn [[_ _ shape]] (let [schema (mu/update-properties schema assoc ::extracted true)]
(str prefix shape))) (swap! *definitions* conj (format-multi schema children))
(str/join ",\n")) title))))
header (cond-> "multi" (defn- format-merge
(some? title) (str " " title) [schema children]
:always (str " [dispatch=" (d/name dispatcher) "]"))]
(str header " {\n" entries "\n" (pad "}" level)))))) (let [props (m/properties schema)
entries (->> children
(map (fn [shape]
(pad shape 1)))
(str/join ",\n"))
title (some-> (:title props) str/camel str/capital)
header (str "merge type " title)]
(str header " {\n" entries "\n}")))
(defmethod visit :merge (defmethod visit :merge
[_ schema children _] [_ schema children {:keys [::level] :as options}]
(let [entries (str/join ",\n" children) (let [props (m/properties schema)
props (m/properties schema) title (some-> (:title props) str/camel str/capital)
title (or (some-> (:title props) str/camel str/capital) extracted? (get props ::extracted false)]
"<untitled>")]
(str "merge type " title " { \n" entries "\n}\n"))) (cond
(or (zero? level) extracted?)
(format-merge schema children)
:else
(let [schema (mu/update-properties schema assoc ::extracted true)]
(swap! *definitions* conj
(format-merge schema children))
title))))
(defmethod visit ::sm/one-of (defmethod visit ::sm/one-of
[_ _ children _] [_ _ children _]
@@ -219,45 +274,37 @@
(map d/name) (map d/name)
(str/join "|")) ")"))) (str/join "|")) ")")))
(defmethod visit :schema [_ schema children options] (defmethod visit :schema
(visit ::m/schema schema children options)) [_ schema children options]
(let [props (m/properties schema)
(defmethod visit ::m/schema title (some-> (:title props) str/camel str/capital)
[_ schema _ {:keys [::level ::limit ::max-level] :as options}] extracted? (get props ::extracted false)]
(let [schema' (m/deref schema)
props (merge
(m/properties schema)
(m/properties schema'))
ref (m/-ref schema)
title (:title props)]
(cond (cond
(::inline props) (not title)
(do (visit ::m/schema schema children options)
(if (>= limit max-level)
title
(describe* schema' options)))
(and ref title) extracted?
(do (let [title (or title "<untitled>")]
(when (<= limit max-level) (str "type " title ": "
(swap! *definitions* conj (describe* schema' (assoc options ::base-limit limit)))) (visit ::m/schema schema children options)))
title)
(>= limit max-level)
(or title
(some-> ref d/name str/camel str/capital)
"<untitled>")
:else :else
(describe* schema' (assoc options ::base-level level ::base-limit limit))))) (let [schema (mu/update-properties schema assoc ::extracted true)
title (or title "<untitled>")]
(swap! *definitions* conj
(str "type " title ": "
(visit ::m/schema schema children (update options ::level inc))))
title))))
(defmethod visit ::m/schema
[_ schema _ {:keys [::level] :as options}]
(let [schema' (m/deref schema)]
(describe* schema' (assoc options ::base-level level))))
(defn describe* [s options] (defn describe* [s options]
(letfn [(walk-fn [schema path children {:keys [::base-level ::base-limit] :or {base-level 0 base-limit 0} :as options}] (letfn [(walk-fn [schema path children {:keys [::base-level] :or {base-level 0} :as options}]
(let [options (assoc options (let [options (assoc options ::level (+ base-level (count path)))]
::limit (+ base-limit (count path))
::level (+ base-level (count path)))]
(visit (m/type schema) schema children options)))] (visit (m/type schema) schema children options)))]
(m/walk s walk-fn options))) (m/walk s walk-fn options)))
@@ -275,8 +322,7 @@
(mu/update-properties assoc ::root true)) (mu/update-properties assoc ::root true))
options (into {::m/walk-entry-vals true options (into {::m/walk-entry-vals true
::level 0 ::level 0}
::max-level 300}
options)] options)]
(binding [*definitions* defs] (binding [*definitions* defs]

View File

@@ -6,6 +6,8 @@
(ns app.common.schema.openapi (ns app.common.schema.openapi
(:require (:require
[app.common.data :as d]
[app.common.schema :as-alias sm]
[clojure.set :as set] [clojure.set :as set]
[cuerdas.core :as str] [cuerdas.core :as str]
[malli.core :as m])) [malli.core :as m]))
@@ -15,16 +17,44 @@
(declare transform*) (declare transform*)
(defmulti visit (fn [name _schema _children _options] name) :default ::default) (defmulti visit (fn [name _schema _children _options] name) :default ::default)
(defmethod visit ::default [_ _ _ _] {})
(defmethod visit ::default [_ schema _ _]
(let [props (m/type-properties schema)]
(d/without-nils
{:type (get props ::type)
:format (get props ::format)
:title (get props :title)
:description (get props :description)})))
(defmethod visit :> [_ _ [value] _] {:type "number" :exclusiveMinimum value}) (defmethod visit :> [_ _ [value] _] {:type "number" :exclusiveMinimum value})
(defmethod visit :>= [_ _ [value] _] {:type "number" :minimum value}) (defmethod visit :>= [_ _ [value] _] {:type "number" :minimum value})
(defmethod visit :< [_ _ [value] _] {:type "number" :exclusiveMaximum value}) (defmethod visit :< [_ _ [value] _] {:type "number" :exclusiveMaximum value})
(defmethod visit :<= [_ _ [value] _] {:type "number" :maximum value}) (defmethod visit :<= [_ _ [value] _] {:type "number" :maximum value})
(defmethod visit := [_ _ [value] _] {:const value})
(defmethod visit := [_ schema children _]
(let [props (m/properties schema)
type (get props :type :string)]
(d/without-nils
{:type (or (get props ::type)
(d/name type))
:enum (if (= :string type)
(mapv d/name children)
(vec children))})))
(defmethod visit :not= [_ _ _ _] {}) (defmethod visit :not= [_ _ _ _] {})
(defmethod visit :fn [_ _ _ _]
nil)
(defmethod visit ::sm/contains-any [_ _ _ _]
nil)
(defmethod visit :not [_ _ children _] {:not (last children)}) (defmethod visit :not [_ _ children _] {:not (last children)})
(defmethod visit :and [_ _ children _] {:allOf children}) (defmethod visit :and [_ _ children _]
{:allOf (keep not-empty children)})
(defmethod visit :or [_ _ children _] {:anyOf children}) (defmethod visit :or [_ _ children _] {:anyOf children})
(defmethod visit :orn [_ _ children _] {:anyOf (map last children)}) (defmethod visit :orn [_ _ children _] {:anyOf (map last children)})
@@ -71,14 +101,28 @@
:minProperties :minProperties
:maxProperties)) :maxProperties))
(defmethod visit :vector [_ schema children _] (defmethod visit :any [_ _ _ _]
(let [child (-> schema m/children first) {:description "Any Value"})
props (m/properties (m/deref child))]
(minmax-properties (defmethod visit ::sm/set [_ schema children _]
{:type "array", :items (first children) :title (:title props)} (minmax-properties
schema {:type "array", :items (first children), :uniqueItems true}
:minItems schema
:maxItems))) :minItems
:maxItems))
(defmethod visit ::sm/vec [_ schema children _]
(minmax-properties
{:type "array", :items (first children)}
schema
:minItems
:maxItems))
(defmethod visit :vector [_ schema children options]
(visit ::sm/vec schema children options))
(defmethod visit :set [_ schema children options]
(visit ::sm/set schema children options))
(defmethod visit :sequential [_ schema children _] (defmethod visit :sequential [_ schema children _]
(minmax-properties (minmax-properties
@@ -87,36 +131,64 @@
:minItems :minItems
:maxItems)) :maxItems))
(defmethod visit :set [_ schema children _] (defmethod visit :enum [_ _ children options]
(minmax-properties (merge (some-> (m/-infer children) (transform* options)) {:enum children}))
{:type "array", :items (first children), :uniqueItems true}
schema (defmethod visit :maybe [_ _ children _]
:minItems (let [children (first children)]
:maxItems)) (assoc children :nullable true)))
(defmethod visit :tuple [_ _ children _]
{:type "array", :items children, :additionalItems false})
(defmethod visit :enum [_ _ children options] (merge (some-> (m/-infer children) (transform* options)) {:enum children}))
(defmethod visit :maybe [_ _ children _] {:oneOf (conj children {:type "null"})})
(defmethod visit :tuple [_ _ children _] {:type "array", :items children, :additionalItems false})
(defmethod visit :re [_ schema _ options] (defmethod visit :re [_ schema _ options]
{:type "string", :pattern (str (first (m/children schema options)))}) {:type "string", :pattern (str (first (m/children schema options)))})
(defmethod visit :nil [_ _ _ _] {:type "null"}) (defmethod visit :nil [_ _ _ _] {:type "null"})
(defmethod visit :string [_ schema _ _] (defmethod visit :string [_ schema _ _]
(merge {:type "string"} (-> schema m/properties (select-keys [:min :max]) (set/rename-keys {:min :minLength, :max :maxLength})))) (merge {:type "string"} (-> schema m/properties (select-keys [:min :max]) (set/rename-keys {:min :minLength, :max :maxLength}))))
(defmethod visit ::sm/one-of [_ _ children _]
(let [options (->> (first children)
(mapv d/name))]
{:type "string"
:enum options}))
(defmethod visit :int [_ schema _ _] (defmethod visit :int [_ schema _ _]
(merge {:type "integer"} (-> schema m/properties (select-keys [:min :max]) (set/rename-keys {:min :minimum, :max :maximum})))) (minmax-properties
{:type "integer"}
schema
:minimum
:maximum))
(defmethod visit :double [_ schema _ _] (defmethod visit :double [_ schema _ _]
(merge {:type "number"} (minmax-properties
(-> schema m/properties (select-keys [:min :max]) (set/rename-keys {:min :minimum, :max :maximum})))) {:type "number"
:format "double"}
schema
:minimum
:maximum))
(defmethod visit ::sm/int
[_ schema children options]
(visit :int schema children options))
(defmethod visit ::sm/double
[_ schema children options]
(visit :double schema children options))
(defmethod visit :boolean [_ _ _ _] {:type "boolean"}) (defmethod visit :boolean [_ _ _ _] {:type "boolean"})
(defmethod visit ::sm/boolean [_ _ _ _] {:type "boolean"})
(defmethod visit :keyword [_ _ _ _] {:type "string"}) (defmethod visit :keyword [_ _ _ _] {:type "string"})
(defmethod visit :qualified-keyword [_ _ _ _] {:type "string"}) (defmethod visit :qualified-keyword [_ _ _ _] {:type "string"})
(defmethod visit :symbol [_ _ _ _] {:type "string"}) (defmethod visit :symbol [_ _ _ _] {:type "string"})
(defmethod visit :qualified-symbol [_ _ _ _] {:type "string"}) (defmethod visit :qualified-symbol [_ _ _ _] {:type "string"})
(defmethod visit :uuid [_ _ _ _] {:type "string" :format "uuid"}) (defmethod visit :uuid [_ _ _ _] {:type "string" :format "uuid"})
(defmethod visit ::sm/uuid [_ _ _ _] {:type "string" :format "uuid"})
(defmethod visit :schema [_ schema children options] (defmethod visit :schema [_ schema children options]
(visit ::m/schema schema children options)) (visit ::m/schema schema children options))
@@ -124,11 +196,14 @@
(defmethod visit ::m/schema [_ schema _ options] (defmethod visit ::m/schema [_ schema _ options]
(let [result (transform* (m/deref schema) options) (let [result (transform* (m/deref schema) options)
defpath (::definitions-path options "#/definitions/")] defpath (::definitions-path options "#/definitions/")]
(if-let [ref (m/-ref schema)]
(let [rkey (str/concat (str/camel (namespace ref)) "$" (name ref))] (if (::embed options)
(some-> *definitions* (swap! assoc rkey result)) result
{"$ref" (str/concat defpath rkey)}) (if-let [ref (m/-ref schema)]
result))) (let [rkey (str/concat (str/camel (namespace ref)) "$" (name ref))]
(some-> *definitions* (swap! assoc rkey result))
{"$ref" (str/concat defpath rkey)})
result))))
(defmethod visit :merge [_ schema _ options] (transform* (m/deref schema) options)) (defmethod visit :merge [_ schema _ options] (transform* (m/deref schema) options))
(defmethod visit :union [_ schema _ options] (transform* (m/deref schema) options)) (defmethod visit :union [_ schema _ options] (transform* (m/deref schema) options))

View File

@@ -60,16 +60,17 @@
{:type ::hex-color {:type ::hex-color
:pred hex-color-string? :pred hex-color-string?
:type-properties :type-properties
{:title "hex-color" {:title "HexColor"
:description "HEX Color String" :description "HEX Color String"
:error/message "expected a valid HEX color" :error/message "expected a valid HEX color"
:error/code "errors.invalid-hex-color" :error/code "errors.invalid-hex-color"
:gen/gen hex-color-generator :gen/gen hex-color-generator
::oapi/type "integer" ::oapi/type "string"
::oapi/format "int64"}})) ::oapi/format "rgb"}}))
(def schema:plain-color (def schema:plain-color
[:map [:color schema:hex-color]]) [:map {:title "PlainColorAttrs"}
[:color schema:hex-color]])
(def schema:image (def schema:image
[:map {:title "ImageColor" :closed true} [:map {:title "ImageColor" :closed true}
@@ -85,7 +86,8 @@
(sm/keys schema:image)) (sm/keys schema:image))
(def schema:image-color (def schema:image-color
[:map [:image schema:image]]) [:map {:title "ImageColorAttrs"}
[:image schema:image]])
(def gradient-types (def gradient-types
#{:linear :radial}) #{:linear :radial})
@@ -110,10 +112,11 @@
(sm/keys schema:gradient)) (sm/keys schema:gradient))
(def schema:gradient-color (def schema:gradient-color
[:map [:gradient schema:gradient]]) [:map {:title "GradientColorAttrs"}
[:gradient schema:gradient]])
(def schema:color-attrs (def schema:color-attrs
[:map {:title "ColorAttrs" :closed true} [:map {:title "GenericColorAttrs" :closed true}
[:opacity {:optional true} [::sm/number {:min 0 :max 1}]] [:opacity {:optional true} [::sm/number {:min 0 :max 1}]]
[:ref-id {:optional true} ::sm/uuid] [:ref-id {:optional true} ::sm/uuid]
[:ref-file {:optional true} ::sm/uuid]]) [:ref-file {:optional true} ::sm/uuid]])
@@ -132,7 +135,7 @@
(into required-color-attrs (sm/keys schema:color-attrs))) (into required-color-attrs (sm/keys schema:color-attrs)))
(def schema:library-color-attrs (def schema:library-color-attrs
[:map {:title "ColorAttrs" :closed true} [:map {:title "LibraryColorAttrs" :closed true}
[:id ::sm/uuid] [:id ::sm/uuid]
[:name ::sm/text] [:name ::sm/text]
[:path {:optional true} :string] [:path {:optional true} :string]

View File

@@ -14,12 +14,12 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def schema:grid-color (def schema:grid-color
[:map {:title "PageGridColor"} [:map {:title "GridColor"}
[:color clr/schema:hex-color] [:color clr/schema:hex-color]
[:opacity ::sm/safe-number]]) [:opacity ::sm/safe-number]])
(def schema:column-params (def schema:column-params
[:map [:map {:title "ColumnGridParams"}
[:color schema:grid-color] [:color schema:grid-color]
[:type {:optional true} [::sm/one-of #{:stretch :left :center :right}]] [:type {:optional true} [::sm/one-of #{:stretch :left :center :right}]]
[:size {:optional true} [:maybe ::sm/safe-number]] [:size {:optional true} [:maybe ::sm/safe-number]]
@@ -28,7 +28,7 @@
[:gutter {:optional true} [:maybe ::sm/safe-number]]]) [:gutter {:optional true} [:maybe ::sm/safe-number]]])
(def schema:square-params (def schema:square-params
[:map [:map {:title "SquareGridParams"}
[:size {:optional true} [:maybe ::sm/safe-number]] [:size {:optional true} [:maybe ::sm/safe-number]]
[:color schema:grid-color]]) [:color schema:grid-color]])
@@ -37,19 +37,19 @@
:dispatch :type :dispatch :type
:decode/json #(update % :type keyword)} :decode/json #(update % :type keyword)}
[:column [:column
[:map [:map {:title "ColumnGridAttrs"}
[:type [:= :column]] [:type [:= :column]]
[:display :boolean] [:display :boolean]
[:params schema:column-params]]] [:params schema:column-params]]]
[:row [:row
[:map [:map {:title "RowGridAttrs"}
[:type [:= :row]] [:type [:= :row]]
[:display :boolean] [:display :boolean]
[:params schema:column-params]]] [:params schema:column-params]]]
[:square [:square
[:map [:map {:title "SquareGridAttrs"}
[:type [:= :square]] [:type [:= :square]]
[:display :boolean] [:display :boolean]
[:params schema:square-params]]]]) [:params schema:square-params]]]])

View File

@@ -18,6 +18,7 @@
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.schema.generators :as sg] [app.common.schema.generators :as sg]
[app.common.schema.openapi :as oapi]
[app.common.svg.path :as svg.path] [app.common.svg.path :as svg.path]
[app.common.transit :as t] [app.common.transit :as t]
[app.common.types.path :as-alias path] [app.common.types.path :as-alias path]
@@ -537,7 +538,8 @@
(sg/fmap from-plain))] (sg/fmap from-plain))]
{:pred path-data? {:pred path-data?
:type-properties :type-properties
{:gen/gen generator {::oapi/type "string"
:gen/gen generator
:encode/json identity :encode/json identity
:decode/json (fn [s] :decode/json (fn [s]
(cond (cond

View File

@@ -24,7 +24,7 @@
(def schema:plugin-data (def schema:plugin-data
(sm/register! (sm/register!
^{::sm/type ::plugin-data} ^{::sm/type ::plugin-data}
[:map-of {:gen/max 5} [:map-of {:gen/max 5 :title "PluginsData"}
schema:keyword schema:keyword
[:map-of {:gen/max 5} [:map-of {:gen/max 5}
schema:string schema:string

View File

@@ -184,7 +184,7 @@
[:height ::sm/safe-number]]) [:height ::sm/safe-number]])
(def schema:shape-generic-attrs (def schema:shape-generic-attrs
[:map {:title "ShapeAttrs"} [:map {:title "ShapeGenericAttrs"}
[:page-id {:optional true} ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid] [:component-id {:optional true} ::sm/uuid]
[:component-file {:optional true} ::sm/uuid] [:component-file {:optional true} ::sm/uuid]

View File

@@ -109,8 +109,8 @@
(def check-animation! (def check-animation!
(sm/check-fn schema:animation)) (sm/check-fn schema:animation))
(def schema:interaction-attrs (def schema:generic-interaction-attrs
[:map {:title "InteractionAttrs"} [:map {:title "GenericInteractionAttrs"}
[:action-type {:optional true} [::sm/one-of action-types]] [:action-type {:optional true} [::sm/one-of action-types]]
[:event-type {:optional true} [::sm/one-of event-types]] [:event-type {:optional true} [::sm/one-of event-types]]
[:destination {:optional true} [:maybe ::sm/uuid]] [:destination {:optional true} [:maybe ::sm/uuid]]
@@ -124,7 +124,7 @@
[:url {:optional true} :string]]) [:url {:optional true} :string]])
(def schema:navigate-interaction (def schema:navigate-interaction
[:map [:map {:title "NavigateInteraction"}
[:action-type [:= :navigate]] [:action-type [:= :navigate]]
[:event-type [::sm/one-of event-types]] [:event-type [::sm/one-of event-types]]
[:destination {:optional true} [:maybe ::sm/uuid]] [:destination {:optional true} [:maybe ::sm/uuid]]
@@ -132,7 +132,7 @@
[:animation {:optional true} schema:animation]]) [:animation {:optional true} schema:animation]])
(def schema:open-overlay-interaction (def schema:open-overlay-interaction
[:map [:map {:title "OpenOverlayInteraction"}
[:action-type [:= :open-overlay]] [:action-type [:= :open-overlay]]
[:event-type [::sm/one-of event-types]] [:event-type [::sm/one-of event-types]]
[:overlay-position ::gpt/point] [:overlay-position ::gpt/point]
@@ -144,7 +144,7 @@
[:position-relative-to {:optional true} [:maybe ::sm/uuid]]]) [:position-relative-to {:optional true} [:maybe ::sm/uuid]]])
(def schema:toggle-overlay-interaction (def schema:toggle-overlay-interaction
[:map [:map {:title "ToggleOverlayInteraction"}
[:action-type [:= :toggle-overlay]] [:action-type [:= :toggle-overlay]]
[:event-type [::sm/one-of event-types]] [:event-type [::sm/one-of event-types]]
[:overlay-position ::gpt/point] [:overlay-position ::gpt/point]
@@ -156,7 +156,7 @@
[:position-relative-to {:optional true} [:maybe ::sm/uuid]]]) [:position-relative-to {:optional true} [:maybe ::sm/uuid]]])
(def schema:close-overlay-interaction (def schema:close-overlay-interaction
[:map [:map {:title "CloseOverlayInteraction"}
[:action-type [:= :close-overlay]] [:action-type [:= :close-overlay]]
[:event-type [::sm/one-of event-types]] [:event-type [::sm/one-of event-types]]
[:destination {:optional true} [:maybe ::sm/uuid]] [:destination {:optional true} [:maybe ::sm/uuid]]
@@ -164,32 +164,33 @@
[:position-relative-to {:optional true} [:maybe ::sm/uuid]]]) [:position-relative-to {:optional true} [:maybe ::sm/uuid]]])
(def schema:prev-scren-interaction (def schema:prev-scren-interaction
[:map [:map {:title "PrevScreenInteraction"}
[:action-type [:= :prev-screen]] [:action-type [:= :prev-screen]]
[:event-type [::sm/one-of event-types]]]) [:event-type [::sm/one-of event-types]]])
(def schema:open-url-interaction (def schema:open-url-interaction
[:map [:map {:title "OpenUrlInteraction"}
[:action-type [:= :open-url]] [:action-type [:= :open-url]]
[:event-type [::sm/one-of event-types]] [:event-type [::sm/one-of event-types]]
[:url :string]]) [:url :string]])
(def schema:interaction (def schema:interaction
[:and {:title "Interaction" [:schema {:title "Interaction"
:gen/gen (sg/one-of (sg/generator schema:navigate-interaction) :gen/gen (sg/one-of (sg/generator schema:navigate-interaction)
(sg/generator schema:open-overlay-interaction) (sg/generator schema:open-overlay-interaction)
(sg/generator schema:close-overlay-interaction) (sg/generator schema:close-overlay-interaction)
(sg/generator schema:toggle-overlay-interaction) (sg/generator schema:toggle-overlay-interaction)
(sg/generator schema:prev-scren-interaction) (sg/generator schema:prev-scren-interaction)
(sg/generator schema:open-url-interaction))} (sg/generator schema:open-url-interaction))}
schema:interaction-attrs [:and
[:multi {:dispatch :action-type} schema:generic-interaction-attrs
[:navigate schema:navigate-interaction] [:multi {:dispatch :action-type :title "InteractionAttrs"}
[:open-overlay schema:open-overlay-interaction] [:navigate schema:navigate-interaction]
[:toggle-overlay schema:toggle-overlay-interaction] [:open-overlay schema:open-overlay-interaction]
[:close-overlay schema:close-overlay-interaction] [:toggle-overlay schema:toggle-overlay-interaction]
[:prev-screen schema:prev-scren-interaction] [:close-overlay schema:close-overlay-interaction]
[:open-url schema:open-url-interaction]]]) [:prev-screen schema:prev-scren-interaction]
[:open-url schema:open-url-interaction]]]])
(sm/register! ::interaction schema:interaction) (sm/register! ::interaction schema:interaction)

View File

@@ -7,7 +7,6 @@
(ns app.common.types.shape.shadow (ns app.common.types.shape.shadow
(:require (:require
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.schema.generators :as sg]
[app.common.types.color :as ctc])) [app.common.types.color :as ctc]))
(def styles #{:drop-shadow :inner-shadow}) (def styles #{:drop-shadow :inner-shadow})
@@ -15,10 +14,7 @@
(def schema:shadow (def schema:shadow
[:map {:title "Shadow"} [:map {:title "Shadow"}
[:id [:maybe ::sm/uuid]] [:id [:maybe ::sm/uuid]]
[:style [:style [::sm/one-of styles]]
[:and {:gen/gen (sg/elements styles)}
:keyword
[::sm/one-of styles]]]
[:offset-x ::sm/safe-number] [:offset-x ::sm/safe-number]
[:offset-y ::sm/safe-number] [:offset-y ::sm/safe-number]
[:blur ::sm/safe-number] [:blur ::sm/safe-number]

View File

@@ -8,6 +8,7 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.schema.generators :as sg]
[clojure.data :as data] [clojure.data :as data]
[clojure.set :as set] [clojure.set :as set]
[cuerdas.core :as str] [cuerdas.core :as str]
@@ -56,7 +57,8 @@
(into #{} (keys token-type->dtcg-token-type))) (into #{} (keys token-type->dtcg-token-type)))
(def token-name-ref (def token-name-ref
[:and :string [:re #"^(?!\$)([a-zA-Z0-9-$_]+\.?)*(?<!\.)$"]]) [:re {:title "TokenNameRef" :gen/gen sg/text}
#"^(?!\$)([a-zA-Z0-9-$_]+\.?)*(?<!\.)$"])
(def ^:private schema:color (def ^:private schema:color
[:map [:map
@@ -66,7 +68,7 @@
(def color-keys (schema-keys schema:color)) (def color-keys (schema-keys schema:color))
(def ^:private schema:border-radius (def ^:private schema:border-radius
[:map [:map {:title "BorderRadiusTokenAttrs"}
[:r1 {:optional true} token-name-ref] [:r1 {:optional true} token-name-ref]
[:r2 {:optional true} token-name-ref] [:r2 {:optional true} token-name-ref]
[:r3 {:optional true} token-name-ref] [:r3 {:optional true} token-name-ref]
@@ -81,7 +83,7 @@
(def stroke-width-keys (schema-keys schema:stroke-width)) (def stroke-width-keys (schema-keys schema:stroke-width))
(def ^:private schema:sizing (def ^:private schema:sizing
[:map [:map {:title "SizingTokenAttrs"}
[:width {:optional true} token-name-ref] [:width {:optional true} token-name-ref]
[:height {:optional true} token-name-ref] [:height {:optional true} token-name-ref]
[:layout-item-min-w {:optional true} token-name-ref] [:layout-item-min-w {:optional true} token-name-ref]
@@ -92,44 +94,46 @@
(def sizing-keys (schema-keys schema:sizing)) (def sizing-keys (schema-keys schema:sizing))
(def ^:private schema:opacity (def ^:private schema:opacity
[:map [:map {:title "OpacityTokenAttrs"}
[:opacity {:optional true} token-name-ref]]) [:opacity {:optional true} token-name-ref]])
(def opacity-keys (schema-keys schema:opacity)) (def opacity-keys (schema-keys schema:opacity))
(def ^:private schema:spacing-gap (def ^:private schema:spacing-gap
[:map [:map {:title "SpacingGapTokenAttrs"}
[:row-gap {:optional true} token-name-ref] [:row-gap {:optional true} token-name-ref]
[:column-gap {:optional true} token-name-ref]]) [:column-gap {:optional true} token-name-ref]])
(def ^:private schema:spacing-padding (def ^:private schema:spacing-padding
[:map [:map {:title "SpacingPaddingTokenAttrs"}
[:p1 {:optional true} token-name-ref] [:p1 {:optional true} token-name-ref]
[:p2 {:optional true} token-name-ref] [:p2 {:optional true} token-name-ref]
[:p3 {:optional true} token-name-ref] [:p3 {:optional true} token-name-ref]
[:p4 {:optional true} token-name-ref]]) [:p4 {:optional true} token-name-ref]])
(def ^:private schema:spacing-margin (def ^:private schema:spacing-margin
[:map [:map {:title "SpacingMarginTokenAttrs"}
[:m1 {:optional true} token-name-ref] [:m1 {:optional true} token-name-ref]
[:m2 {:optional true} token-name-ref] [:m2 {:optional true} token-name-ref]
[:m3 {:optional true} token-name-ref] [:m3 {:optional true} token-name-ref]
[:m4 {:optional true} token-name-ref]]) [:m4 {:optional true} token-name-ref]])
(def ^:private schema:spacing (def ^:private schema:spacing
(reduce mu/union [schema:spacing-gap (-> (reduce mu/union [schema:spacing-gap
schema:spacing-padding schema:spacing-padding
schema:spacing-margin])) schema:spacing-margin])
(mu/update-properties assoc :title "SpacingTokenAttrs")))
(def spacing-margin-keys (schema-keys schema:spacing-margin)) (def spacing-margin-keys (schema-keys schema:spacing-margin))
(def spacing-keys (schema-keys schema:spacing)) (def spacing-keys (schema-keys schema:spacing))
(def ^:private schema:dimensions (def ^:private schema:dimensions
(reduce mu/union [schema:sizing (-> (reduce mu/union [schema:sizing
schema:spacing schema:spacing
schema:stroke-width schema:stroke-width
schema:border-radius])) schema:border-radius])
(mu/update-properties assoc :title "DimensionsTokenAttrs")))
(def dimensions-keys (schema-keys schema:dimensions)) (def dimensions-keys (schema-keys schema:dimensions))
@@ -140,22 +144,20 @@
(def axis-keys (schema-keys schema:axis)) (def axis-keys (schema-keys schema:axis))
(def ^:private schema:rotation (def ^:private schema:rotation
[:map [:map {:title "RotationTokenAttrs"}
[:rotation {:optional true} token-name-ref]]) [:rotation {:optional true} token-name-ref]])
(def rotation-keys (schema-keys schema:rotation)) (def rotation-keys (schema-keys schema:rotation))
(def ^:private schema:font-size (def ^:private schema:font-size
[:map [:map {:title "FontSizeTokenAttrs"}
[:font-size {:optional true} token-name-ref]]) [:font-size {:optional true} token-name-ref]])
(def font-size-keys (schema-keys schema:font-size)) (def font-size-keys (schema-keys schema:font-size))
(def ^:private schema:letter-spacing (def ^:private schema:letter-spacing
[:map [:map {:title "LetterSpacingTokenAttrs"}
[:letter-spacing {:optional true} token-name-ref]]) [:letter-spacing {:optional true} token-name-ref]])
(def letter-spacing-keys (schema-keys schema:letter-spacing)) (def letter-spacing-keys (schema-keys schema:letter-spacing))
@@ -197,8 +199,9 @@
(def ff-typography-keys (set/difference typography-keys font-size-keys)) (def ff-typography-keys (set/difference typography-keys font-size-keys))
(def ^:private schema:number (def ^:private schema:number
(reduce mu/union [[:map [:line-height {:optional true} token-name-ref]] (-> (reduce mu/union [[:map [:line-height {:optional true} token-name-ref]]
schema:rotation])) schema:rotation])
(mu/update-properties assoc :title "NumberTokenAttrs")))
(def number-keys (schema-keys schema:number)) (def number-keys (schema-keys schema:number))
@@ -215,10 +218,10 @@
number-keys)) number-keys))
(def ^:private schema:tokens (def ^:private schema:tokens
[:map {:title "Applied Tokens"}]) [:map {:title "GenericTokenAttrs"}])
(def schema:applied-tokens (def schema:applied-tokens
[:merge [:merge {:title "AppliedTokens"}
schema:tokens schema:tokens
schema:border-radius schema:border-radius
schema:sizing schema:sizing