Merge pull request #7082 from penpot/niwinz-staging-changes-fix

♻️ Refactor schema references and openapi.json output
This commit is contained in:
Alejandro Alonso 2025-08-20 12:55:16 +02:00 committed by GitHub
commit ef8d2e7418
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 812 additions and 748 deletions

1
.gitignore vendored
View File

@ -31,6 +31,7 @@
/.clj-kondo/.cache /.clj-kondo/.cache
/_dump /_dump
/notes /notes
/playground/
/backend/*.md /backend/*.md
/backend/*.sql /backend/*.sql
/backend/*.txt /backend/*.txt

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

@ -103,25 +103,25 @@
(sm/encoder ctp/schema:page sm/json-transformer)) (sm/encoder ctp/schema:page sm/json-transformer))
(def encode-shape (def encode-shape
(sm/encoder ::cts/shape sm/json-transformer)) (sm/encoder cts/schema:shape sm/json-transformer))
(def encode-media (def encode-media
(sm/encoder ::ctf/media sm/json-transformer)) (sm/encoder ctf/schema:media sm/json-transformer))
(def encode-component (def encode-component
(sm/encoder ::ctc/component sm/json-transformer)) (sm/encoder ctc/schema:component sm/json-transformer))
(def encode-color (def encode-color
(sm/encoder ctcl/schema:library-color sm/json-transformer)) (sm/encoder ctcl/schema:library-color sm/json-transformer))
(def encode-typography (def encode-typography
(sm/encoder ::cty/typography sm/json-transformer)) (sm/encoder cty/schema:typography sm/json-transformer))
(def encode-tokens-lib (def encode-tokens-lib
(sm/encoder ::cto/tokens-lib sm/json-transformer)) (sm/encoder cto/schema:tokens-lib sm/json-transformer))
(def encode-plugin-data (def encode-plugin-data
(sm/encoder ::ctpg/plugin-data sm/json-transformer)) (sm/encoder ctpg/schema:plugin-data sm/json-transformer))
(def encode-storage-object (def encode-storage-object
(sm/encoder schema:storage-object sm/json-transformer)) (sm/encoder schema:storage-object sm/json-transformer))
@ -138,7 +138,7 @@
(sm/decoder ctf/schema:media sm/json-transformer)) (sm/decoder ctf/schema:media sm/json-transformer))
(def decode-component (def decode-component
(sm/decoder ::ctc/component sm/json-transformer)) (sm/decoder ctc/schema:component sm/json-transformer))
(def decode-color (def decode-color
(sm/decoder ctcl/schema:library-color sm/json-transformer)) (sm/decoder ctcl/schema:library-color sm/json-transformer))
@ -147,19 +147,19 @@
(sm/decoder schema:file sm/json-transformer)) (sm/decoder schema:file sm/json-transformer))
(def decode-page (def decode-page
(sm/decoder ::ctp/page sm/json-transformer)) (sm/decoder ctp/schema:page sm/json-transformer))
(def decode-shape (def decode-shape
(sm/decoder ::cts/shape sm/json-transformer)) (sm/decoder cts/schema:shape sm/json-transformer))
(def decode-typography (def decode-typography
(sm/decoder ::cty/typography sm/json-transformer)) (sm/decoder cty/schema:typography sm/json-transformer))
(def decode-tokens-lib (def decode-tokens-lib
(sm/decoder cto/schema:tokens-lib sm/json-transformer)) (sm/decoder cto/schema:tokens-lib sm/json-transformer))
(def decode-plugin-data (def decode-plugin-data
(sm/decoder ::ctpg/plugin-data sm/json-transformer)) (sm/decoder ctpg/schema:plugin-data sm/json-transformer))
(def decode-storage-object (def decode-storage-object
(sm/decoder schema:storage-object sm/json-transformer)) (sm/decoder schema:storage-object sm/json-transformer))
@ -173,31 +173,31 @@
(sm/check-fn schema:manifest)) (sm/check-fn schema:manifest))
(def validate-file (def validate-file
(sm/check-fn ::ctf/file)) (sm/check-fn ctf/schema:file))
(def validate-page (def validate-page
(sm/check-fn ::ctp/page)) (sm/check-fn ctp/schema:page))
(def validate-shape (def validate-shape
(sm/check-fn ::cts/shape)) (sm/check-fn cts/schema:shape))
(def validate-media (def validate-media
(sm/check-fn ::ctf/media)) (sm/check-fn ctf/schema:media))
(def validate-color (def validate-color
(sm/check-fn ctcl/schema:library-color)) (sm/check-fn ctcl/schema:library-color))
(def validate-component (def validate-component
(sm/check-fn ::ctc/component)) (sm/check-fn ctc/schema:component))
(def validate-typography (def validate-typography
(sm/check-fn ::cty/typography)) (sm/check-fn cty/schema:typography))
(def validate-tokens-lib (def validate-tokens-lib
(sm/check-fn ::cto/tokens-lib)) (sm/check-fn cto/schema:tokens-lib))
(def validate-plugin-data (def validate-plugin-data
(sm/check-fn ::ctpg/plugin-data)) (sm/check-fn ctpg/schema:plugin-data))
(def validate-storage-object (def validate-storage-object
(sm/check-fn schema:storage-object)) (sm/check-fn schema:storage-object))

View File

@ -38,15 +38,13 @@
org.im4java.core.Info)) org.im4java.core.Info))
(def schema:upload (def schema:upload
(sm/register! [:map {:title "Upload"}
^{::sm/type ::upload} [:filename :string]
[:map {:title "Upload"} [:size ::sm/int]
[:filename :string] [:path ::fs/path]
[:size ::sm/int] [:mtype {:optional true} :string]
[:path ::fs/path] [:headers {:optional true}
[:mtype {:optional true} :string] [:map-of :string :string]]])
[:headers {:optional true}
[:map-of :string :string]]]))
(def ^:private schema:input (def ^:private schema:input
[:map {:title "Input"} [:map {:title "Input"}

View File

@ -127,7 +127,7 @@
[:project-id ::sm/uuid] [:project-id ::sm/uuid]
[:file-id {:optional true} ::sm/uuid] [:file-id {:optional true} ::sm/uuid]
[:version {:optional true} ::sm/int] [:version {:optional true} ::sm/int]
[:file ::media/upload]]) [:file media/schema:upload]])
(sv/defmethod ::import-binfile (sv/defmethod ::import-binfile
"Import a penpot file in a binary format. If `file-id` is provided, "Import a penpot file in a binary format. If `file-id` is provided,

View File

@ -195,7 +195,7 @@
(def schema:permissions-mixin (def schema:permissions-mixin
[:map {:title "PermissionsMixin"} [:map {:title "PermissionsMixin"}
[:permissions ::perms/permissions]]) [:permissions perms/schema:permissions]])
(def schema:file-with-permissions (def schema:file-with-permissions
[:merge {:title "FileWithPermissions"} [:merge {:title "FileWithPermissions"}
@ -357,7 +357,7 @@
[:id ::sm/uuid] [:id ::sm/uuid]
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:created-at ::ct/inst] [:created-at ::ct/inst]
[:content any?]]) [:content ::sm/any]])
(def schema:get-file-fragment (def schema:get-file-fragment
[:map {:title "get-file-fragment"} [:map {:title "get-file-fragment"}

View File

@ -79,10 +79,9 @@
;; --- MUTATION COMMAND: update-temp-file ;; --- MUTATION COMMAND: update-temp-file
(def ^:private schema:update-temp-file (def ^:private schema:update-temp-file
[:map {:title "update-temp-file"} [:map {:title "update-temp-file"}
[:changes [:vector ::cpc/change]] [:changes [:vector cpc/schema:change]]
[:revn [::sm/int {:min 0}]] [:revn [::sm/int {:min 0}]]
[:session-id ::sm/uuid] [:session-id ::sm/uuid]
[:id ::sm/uuid]]) [:id ::sm/uuid]])

View File

@ -271,7 +271,7 @@
[:map {:title "create-file-object-thumbnail"} [:map {:title "create-file-object-thumbnail"}
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:object-id [:string {:max 250}]] [:object-id [:string {:max 250}]]
[:media ::media/upload] [:media media/schema:upload]
[:tag {:optional true} [:string {:max 50}]]]) [:tag {:optional true} [:string {:max 50}]]])
(sv/defmethod ::create-file-object-thumbnail (sv/defmethod ::create-file-object-thumbnail
@ -381,7 +381,7 @@
[:map {:title "create-file-thumbnail"} [:map {:title "create-file-thumbnail"}
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:revn ::sm/int] [:revn ::sm/int]
[:media ::media/upload]]) [:media media/schema:upload]])
(sv/defmethod ::create-file-thumbnail (sv/defmethod ::create-file-thumbnail
"Creates or updates the file thumbnail. Mainly used for paint the "Creates or updates the file thumbnail. Mainly used for paint the

View File

@ -64,10 +64,10 @@
[:revn {:min 0} ::sm/int] [:revn {:min 0} ::sm/int]
[:vern {:min 0} ::sm/int] [:vern {:min 0} ::sm/int]
[:features {:optional true} ::cfeat/features] [:features {:optional true} ::cfeat/features]
[:changes {:optional true} [:vector ::cpc/change]] [:changes {:optional true} [:vector cpc/schema:change]]
[:changes-with-metadata {:optional true} [:changes-with-metadata {:optional true}
[:vector [:map [:vector [:map
[:changes [:vector ::cpc/change]] [:changes [:vector cpc/schema:change]]
[:hint-origin {:optional true} :keyword] [:hint-origin {:optional true} :keyword]
[:hint-events {:optional true} [:vector [:string {:max 250}]]]]]] [:hint-events {:optional true} [:vector [:string {:max 250}]]]]]]
[:skip-validate {:optional true} ::sm/boolean]]) [:skip-validate {:optional true} ::sm/boolean]])
@ -76,7 +76,7 @@
schema:update-file-result schema:update-file-result
[:vector {:title "update-file-result"} [:vector {:title "update-file-result"}
[:map [:map
[:changes [:vector ::cpc/change]] [:changes [:vector cpc/schema:change]]
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:id ::sm/uuid] [:id ::sm/uuid]
[:revn {:min 0} ::sm/int] [:revn {:min 0} ::sm/int]

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

@ -48,7 +48,7 @@
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:is-local ::sm/boolean] [:is-local ::sm/boolean]
[:name [:string {:max 250}]] [:name [:string {:max 250}]]
[:content ::media/upload]]) [:content media/schema:upload]])
(sv/defmethod ::upload-file-media-object (sv/defmethod ::upload-file-media-object
{::doc/added "1.17" {::doc/added "1.17"

View File

@ -253,7 +253,7 @@
(def ^:private (def ^:private
schema:update-profile-photo schema:update-profile-photo
[:map {:title "update-profile-photo"} [:map {:title "update-profile-photo"}
[:file ::media/upload]]) [:file media/schema:upload]])
(sv/defmethod ::update-profile-photo (sv/defmethod ::update-profile-photo
{:doc/added "1.1" {:doc/added "1.1"

View File

@ -12,7 +12,7 @@
[app.common.features :as cfeat] [app.common.features :as cfeat]
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.time :as ct] [app.common.time :as ct]
[app.common.types.team :as tt] [app.common.types.team :as types.team]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.db :as db] [app.db :as db]
@ -629,7 +629,7 @@
;; assign owner role to new profile ;; assign owner role to new profile
(db/update! conn :team-profile-rel (db/update! conn :team-profile-rel
(get tt/permissions-for-role :owner) (get types.team/permissions-for-role :owner)
{:team-id id :profile-id reassign-to})) {:team-id id :profile-id reassign-to}))
;; and finally, if all other conditions does not match and the ;; and finally, if all other conditions does not match and the
@ -742,7 +742,7 @@
:team-id team-id :team-id team-id
:role role}) :role role})
(let [params (get tt/permissions-for-role role)] (let [params (get types.team/permissions-for-role role)]
;; Only allow single owner on team ;; Only allow single owner on team
(when (= role :owner) (when (= role :owner)
(db/update! conn :team-profile-rel (db/update! conn :team-profile-rel
@ -760,7 +760,7 @@
[:map {:title "update-team-member-role"} [:map {:title "update-team-member-role"}
[:team-id ::sm/uuid] [:team-id ::sm/uuid]
[:member-id ::sm/uuid] [:member-id ::sm/uuid]
[:role ::tt/role]]) [:role types.team/schema:role]])
(sv/defmethod ::update-team-member-role (sv/defmethod ::update-team-member-role
{::doc/added "1.17" {::doc/added "1.17"
@ -810,7 +810,7 @@
(def ^:private schema:update-team-photo (def ^:private schema:update-team-photo
[:map {:title "update-team-photo"} [:map {:title "update-team-photo"}
[:team-id ::sm/uuid] [:team-id ::sm/uuid]
[:file ::media/upload]]) [:file media/schema:upload]])
(sv/defmethod ::update-team-photo (sv/defmethod ::update-team-photo
{::doc/added "1.17" {::doc/added "1.17"

View File

@ -75,7 +75,7 @@
[:map [:map
[:id ::sm/uuid] [:id ::sm/uuid]
[:fullname :string]]] [:fullname :string]]]
[:role ::types.team/role] [:role types.team/schema:role]
[:email ::sm/email]]) [:email ::sm/email]])
(def ^:private check-create-invitation-params (def ^:private check-create-invitation-params
@ -257,7 +257,7 @@
(def ^:private schema:create-team-invitations (def ^:private schema:create-team-invitations
[:map {:title "create-team-invitations"} [:map {:title "create-team-invitations"}
[:team-id ::sm/uuid] [:team-id ::sm/uuid]
[:role ::types.team/role] [:role types.team/schema:role]
[:emails [::sm/set ::sm/email]]]) [:emails [::sm/set ::sm/email]]])
(def ^:private max-invitations-by-request-threshold (def ^:private max-invitations-by-request-threshold
@ -318,7 +318,7 @@
[:features {:optional true} ::cfeat/features] [:features {:optional true} ::cfeat/features]
[:id {:optional true} ::sm/uuid] [:id {:optional true} ::sm/uuid]
[:emails [::sm/set ::sm/email]] [:emails [::sm/set ::sm/email]]
[:role ::types.team/role]]) [:role types.team/schema:role]])
(sv/defmethod ::create-team-with-invitations (sv/defmethod ::create-team-with-invitations
{::doc/added "1.17" {::doc/added "1.17"
@ -403,7 +403,7 @@
[:map {:title "update-team-invitation-role"} [:map {:title "update-team-invitation-role"}
[:team-id ::sm/uuid] [:team-id ::sm/uuid]
[:email ::sm/email] [:email ::sm/email]
[:role ::types.team/role]]) [:role types.team/schema:role]])
(sv/defmethod ::update-team-invitation-role (sv/defmethod ::update-team-invitation-role
{::doc/added "1.17" {::doc/added "1.17"

View File

@ -128,7 +128,7 @@
[:iss :keyword] [:iss :keyword]
[:exp ::ct/inst] [:exp ::ct/inst]
[:profile-id ::sm/uuid] [:profile-id ::sm/uuid]
[:role ::types.team/role] [:role types.team/schema:role]
[:team-id ::sm/uuid] [:team-id ::sm/uuid]
[:member-email ::sm/email] [:member-email ::sm/email]
[:member-id {:optional true} ::sm/uuid]]) [:member-id {:optional true} ::sm/uuid]])

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

@ -10,15 +10,14 @@
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.schema :as sm])) [app.common.schema :as sm]))
(sm/register! (def schema:permissions
^{::sm/type ::permissions} [:map {:title "Permissions"}
[:map {:title "Permissions"} [:type {:gen/elements [:membership :share-link]} :keyword]
[:type {:gen/elements [:membership :share-link]} :keyword] [:is-owner ::sm/boolean]
[:is-owner ::sm/boolean] [:is-admin ::sm/boolean]
[:is-admin ::sm/boolean] [:can-edit ::sm/boolean]
[:can-edit ::sm/boolean] [:can-read ::sm/boolean]
[:can-read ::sm/boolean] [:is-logged ::sm/boolean]])
[:is-logged ::sm/boolean]])
(def valid-roles (def valid-roles
#{:admin :owner :editor :viewer}) #{:admin :owner :editor :viewer})

View File

@ -0,0 +1,36 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns backend-tests.rpc-doc-test
"Internal binfile test, no RPC involved"
(:require
[app.common.json :as json]
[app.common.pprint :as pp]
[app.common.schema :as sm]
[app.common.schema.generators :as sg]
[app.common.schema.test :as smt]
[app.rpc :as-alias rpc]
[app.rpc.doc :as rpc.doc]
[backend-tests.helpers :as th]
[clojure.test :as t]))
(t/use-fixtures :once th/state-init)
(t/deftest openapi-context-json-encode
(smt/check!
(smt/for [context (->> sg/int
(sg/fmap (fn [_]
(rpc.doc/prepare-openapi-context (::rpc/methods th/*system*)))))]
(try
(json/encode context)
true
(catch Throwable _cause
false)))
{:num 30}))

View File

@ -86,7 +86,7 @@
(t/deftest internal-encode-decode (t/deftest internal-encode-decode
(smt/check! (smt/check!
(smt/for [data (->> (cg/map cg/uuid (sg/generator ::cts/shape)) (smt/for [data (->> (cg/map cg/uuid (sg/generator cts/schema:shape))
(cg/not-empty))] (cg/not-empty))]
(let [obj1 (omap/wrap data) (let [obj1 (omap/wrap data)
obj2 (omap/create (deref obj1)) obj2 (omap/create (deref obj1))
@ -103,7 +103,7 @@
(t/deftest fressian-encode-decode (t/deftest fressian-encode-decode
(smt/check! (smt/check!
(smt/for [data (->> (cg/map cg/uuid (sg/generator ::cts/shape)) (smt/for [data (->> (cg/map cg/uuid (sg/generator cts/schema:shape))
(cg/not-empty) (cg/not-empty)
(cg/fmap omap/wrap) (cg/fmap omap/wrap)
(cg/fmap (fn [o] {:objects o})))] (cg/fmap (fn [o] {:objects o})))]
@ -119,7 +119,7 @@
(t/deftest transit-encode-decode (t/deftest transit-encode-decode
(smt/check! (smt/check!
(smt/for [data (->> (cg/map cg/uuid (sg/generator ::cts/shape)) (smt/for [data (->> (cg/map cg/uuid (sg/generator cts/schema:shape))
(cg/not-empty) (cg/not-empty)
(cg/fmap omap/wrap) (cg/fmap omap/wrap)
(cg/fmap (fn [o] {:objects o})))] (cg/fmap (fn [o] {:objects o})))]

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]]
@ -111,20 +112,20 @@
[:type [:= :set-guide]] [:type [:= :set-guide]]
[:page-id ::sm/uuid] [:page-id ::sm/uuid]
[:id ::sm/uuid] [:id ::sm/uuid]
[:params [:maybe ::ctp/guide]]] [:params [:maybe ctp/schema:guide]]]
gen (->> (sg/generator schema) gen (->> (sg/generator schema)
(sg/fmap (fn [change] (sg/fmap (fn [change]
(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"}
[:type [:= :set-flow]] [:type [:= :set-flow]]
[:page-id ::sm/uuid] [:page-id ::sm/uuid]
[:id ::sm/uuid] [:id ::sm/uuid]
[:params [:maybe ::ctp/flow]]] [:params [:maybe ctp/schema:flow]]]
gen (->> (sg/generator schema) gen (->> (sg/generator schema)
(sg/fmap (fn [change] (sg/fmap (fn [change]
@ -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,287 +170,274 @@
: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-option
;; DEPRECATED: remove before 2.3 release [:set-comment-thread-position
;; [:map {:title "SetCommentThreadPositionChange"}
;; Is still there for not cause error when event is received [:comment-thread-id ::sm/uuid]
[:map {:title "SetOptionChange"}]] [:page-id ::sm/uuid]
[:frame-id [:maybe ::sm/uuid]]
[:position [:maybe ::gpt/point]]]]
[:set-comment-thread-position [:add-obj
[:map [:map {:title "AddObjChange"}
[:comment-thread-id ::sm/uuid] [:type [:= :add-obj]]
[:page-id ::sm/uuid] [:id ::sm/uuid]
[:frame-id [:maybe ::sm/uuid]] [:obj cts/schema:shape]
[:position [:maybe ::gpt/point]]]] [:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid]
[:frame-id ::sm/uuid]
[:parent-id {:optional true} [:maybe ::sm/uuid]]
[:index {:optional true} [:maybe :int]]
[:ignore-touched {:optional true} :boolean]]]
[:add-obj [:mod-obj
[:map {:title "AddObjChange"} [:map {:title "ModObjChange"}
[:type [:= :add-obj]] [:type [:= :mod-obj]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:obj :map] [: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]]]]
[:frame-id ::sm/uuid]
[:parent-id {:optional true} [:maybe ::sm/uuid]]
[:index {:optional true} [:maybe :int]]
[:ignore-touched {:optional true} :boolean]]]
[:mod-obj [:del-obj
[:map {:title "ModObjChange"} [:map {:title "DelObjChange"}
[:type [:= :mod-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]
[:operations [:vector {:gen/max 5} schema:operation]]]] [:ignore-touched {:optional true} :boolean]]]
[:del-obj [:set-guide schema:set-guide-change]
[:map {:title "DelObjChange"} [:set-flow schema:set-flow-change]
[:type [:= :del-obj]] [:set-default-grid schema:set-default-grid-change]
[:id ::sm/uuid]
[:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid]
[:ignore-touched {:optional true} :boolean]]]
[:set-guide schema:set-guide-change] [:fix-obj
[:set-flow schema:set-flow-change] [:map {:title "FixObjChange"}
[:set-default-grid schema:set-default-grid-change] [:type [:= :fix-obj]]
[:id ::sm/uuid]
[:fix {:optional true} :keyword]
[:page-id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid]]]
[:fix-obj [:mov-objects
[:map {:title "FixObjChange"} [:map {:title "MovObjectsChange"}
[:type [:= :fix-obj]] [:type [:= :mov-objects]]
[:id ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:fix {:optional true} :keyword] [:component-id {:optional true} ::sm/uuid]
[:page-id {:optional true} ::sm/uuid] [:ignore-touched {:optional true} :boolean]
[:component-id {:optional true} ::sm/uuid]]] [:parent-id ::sm/uuid]
[:shapes ::sm/any]
[:index {:optional true} [:maybe :int]]
[:after-shape {:optional true} ::sm/any]
[:allow-altering-copies {:optional true} :boolean]]]
[:mov-objects [:reorder-children
[:map {:title "MovObjectsChange"} [:map {:title "ReorderChildrenChange"}
[:type [:= :mov-objects]] [: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]]]
[:index {:optional true} [:maybe :int]]
[:after-shape {:optional true} ::sm/any]
[:allow-altering-copies {:optional true} :boolean]]]
[:reorder-children [:add-page
[:map {:title "ReorderChildrenChange"} [:map {:title "AddPageChange"}
[:type [:= :reorder-children]] [:type [:= :add-page]]
[:page-id {:optional true} ::sm/uuid] [:id {:optional true} ::sm/uuid]
[:component-id {:optional true} ::sm/uuid] [:name {:optional true} :string]
[:ignore-touched {:optional true} :boolean] [:page {:optional true} ::sm/any]]]
[:parent-id ::sm/uuid]
[:shapes ::sm/any]]]
[:add-page [:mod-page
[:map {:title "AddPageChange"} [:map {:title "ModPageChange"}
[:type [:= :add-page]] [:type [:= :mod-page]]
[:id {:optional true} ::sm/uuid] [:id ::sm/uuid]
[:name {:optional true} :string] ;; All props are optional, background can be nil because is the
[:page {:optional true} ::sm/any]]] ;; way to remove already set background
[:background {:optional true} [:maybe ctc/schema:hex-color]]
[:name {:optional true} :string]]]
[:mod-page [:set-plugin-data schema:set-plugin-data-change]
[:map {:title "ModPageChange"}
[:type [:= :mod-page]]
[:id ::sm/uuid]
;; All props are optional, background can be nil because is the
;; way to remove already set background
[:background {:optional true} [:maybe ctc/schema:hex-color]]
[:name {:optional true} :string]]]
[:set-plugin-data schema:set-plugin-data-change] [:del-page
[:map {:title "DelPageChange"}
[:type [:= :del-page]]
[:id ::sm/uuid]]]
[:del-page [:mov-page
[:map {:title "DelPageChange"} [:map {:title "MovPageChange"}
[:type [:= :del-page]] [:type [:= :mov-page]]
[:id ::sm/uuid]]] [:id ::sm/uuid]
[:index :int]]]
[:mov-page [:reg-objects
[:map {:title "MovPageChange"} [:map {:title "RegObjectsChange"}
[:type [:= :mov-page]] [:type [:= :reg-objects]]
[:id ::sm/uuid] [:page-id {:optional true} ::sm/uuid]
[:index :int]]] [:component-id {:optional true} ::sm/uuid]
[:shapes [:vector {:gen/max 5} ::sm/uuid]]]]
[:reg-objects [:add-color
[:map {:title "RegObjectsChange"} [:map {:title "AddColorChange"}
[:type [:= :reg-objects]] [:type [:= :add-color]]
[:page-id {:optional true} ::sm/uuid] [:color ctc/schema:library-color]]]
[:component-id {:optional true} ::sm/uuid]
[:shapes [:vector {:gen/max 5} ::sm/uuid]]]]
[:add-color [:mod-color
[:map {:title "AddColorChange"} [:map {:title "ModColorChange"}
[:type [:= :add-color]] [:type [:= :mod-color]]
[:color ctc/schema:library-color]]] [:color ctc/schema:library-color]]]
[:mod-color [:del-color
[:map {:title "ModColorChange"} [:map {:title "DelColorChange"}
[:type [:= :mod-color]] [:type [:= :del-color]]
[:color ctc/schema:library-color]]] [:id ::sm/uuid]]]
[:del-color [:add-media
[:map {:title "DelColorChange"} [:map {:title "AddMediaChange"}
[:type [:= :del-color]] [:type [:= :add-media]]
[:id ::sm/uuid]]] [:object ctf/schema:media]]]
;; DEPRECATED: remove before 2.3 [:mod-media
[:add-recent-color [:map {:title "ModMediaChange"}
[:map {:title "AddRecentColorChange"}]] [:type [:= :mod-media]]
[:object ctf/schema:media]]]
[:add-media [:del-media
[:map {:title "AddMediaChange"} [:map {:title "DelMediaChange"}
[:type [:= :add-media]] [:type [:= :del-media]]
[:object ctf/schema:media]]] [:id ::sm/uuid]]]
[:mod-media [:add-component
[:map {:title "ModMediaChange"} [:map {:title "AddComponentChange"}
[:type [:= :mod-media]] [:type [:= :add-component]]
[:object ctf/schema:media]]] [: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]]]
[:del-media [:mod-component
[:map {:title "DelMediaChange"} [:map {:title "ModCompoenentChange"}
[:type [:= :del-media]] [:type [:= :mod-component]]
[:id ::sm/uuid]]] [:id ::sm/uuid]
[:shapes {:optional true} [:vector {:gen/max 3} ::sm/any]]
[:name {:optional true} :string]
[:variant-id {:optional true} ::sm/uuid]
[:variant-properties {:optional true} [:vector ctv/schema:variant-property]]]]
[:add-component [:del-component
[:map {:title "AddComponentChange"} [:map {:title "DelComponentChange"}
[:type [:= :add-component]] [:type [:= :del-component]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] ;; when it is an undo of a cut-paste, we need to undo the movement
[:shapes {:optional true} [:vector {:gen/max 3} ::sm/any]] ;; of the shapes so we need to move them delta
[:path {:optional true} :string]]] [:delta {:optional true} ::gpt/point]
[:skip-undelete? {:optional true} :boolean]]]
[:mod-component [:restore-component
[:map {:title "ModCompoenentChange"} [:map {:title "RestoreComponentChange"}
[:type [:= :mod-component]] [:type [:= :restore-component]]
[:id ::sm/uuid] [:id ::sm/uuid]
[:shapes {:optional true} [:vector {:gen/max 3} ::sm/any]] [:page-id ::sm/uuid]]]
[:name {:optional true} :string]
[:variant-id {:optional true} ::sm/uuid]
[:variant-properties {:optional true} [:vector ::ctv/variant-property]]]]
[:del-component [:purge-component
[:map {:title "DelComponentChange"} [:map {:title "PurgeComponentChange"}
[:type [:= :del-component]] [:type [:= :purge-component]]
[:id ::sm/uuid] [:id ::sm/uuid]]]
;; when it is an undo of a cut-paste, we need to undo the movement
;; of the shapes so we need to move them delta
[:delta {:optional true} ::gpt/point]
[:skip-undelete? {:optional true} :boolean]]]
[:restore-component [:add-typography
[:map {:title "RestoreComponentChange"} [:map {:title "AddTypogrphyChange"}
[:type [:= :restore-component]] [:type [:= :add-typography]]
[:id ::sm/uuid] [:typography ctt/schema:typography]]]
[:page-id ::sm/uuid]]]
[:purge-component [:mod-typography
[:map {:title "PurgeComponentChange"} [:map {:title "ModTypogrphyChange"}
[:type [:= :purge-component]] [:type [:= :mod-typography]]
[:id ::sm/uuid]]] [:typography ctt/schema:typography]]]
[:add-typography [:del-typography
[:map {:title "AddTypogrphyChange"} [:map {:title "DelTypogrphyChange"}
[:type [:= :add-typography]] [:type [:= :del-typography]]
[:typography ::ctt/typography]]] [:id ::sm/uuid]]]
[:mod-typography [:update-active-token-themes
[:map {:title "ModTypogrphyChange"} [:map {:title "UpdateActiveTokenThemes"}
[:type [:= :mod-typography]] [:type [:= :update-active-token-themes]]
[:typography ::ctt/typography]]] [:theme-paths [:set :string]]]]
[:del-typography [:rename-token-set-group
[:map {:title "DelTypogrphyChange"} [:map {:title "RenameTokenSetGroup"}
[:type [:= :del-typography]] [:type [:= :rename-token-set-group]]
[:id ::sm/uuid]]] [:set-group-path [:vector :string]]
[:set-group-fname :string]]]
[:update-active-token-themes [:move-token-set
[:map {:title "UpdateActiveTokenThemes"} [:map {:title "MoveTokenSet"}
[:type [:= :update-active-token-themes]] [:type [:= :move-token-set]]
[:theme-paths [:set :string]]]] [:from-path [:vector :string]]
[:to-path [:vector :string]]
[:before-path [:maybe [:vector :string]]]
[:before-group [:maybe :boolean]]]]
[:rename-token-set-group [:move-token-set-group
[:map {:title "RenameTokenSetGroup"} [:map {:title "MoveTokenSetGroup"}
[:type [:= :rename-token-set-group]] [:type [:= :move-token-set-group]]
[: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 [:set-token-theme
[:map {:title "MoveTokenSet"} [:map {:title "SetTokenThemeChange"}
[:type [:= :move-token-set]] [: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]]]]
[:move-token-set-group [:set-tokens-lib
[:map {:title "MoveTokenSetGroup"} [:map {:title "SetTokensLib"}
[:type [:= :move-token-set-group]] [:type [:= :set-tokens-lib]]
[:from-path [:vector :string]] [:tokens-lib ::sm/any]]]
[:to-path [:vector :string]]
[:before-path [:maybe [:vector :string]]]
[:before-group [:maybe :boolean]]]]
[:set-token-theme [:set-token-set
[:map {:title "SetTokenThemeChange"} [:map {:title "SetTokenSetChange"}
[:type [:= :set-token-theme]] [:type [:= :set-token-set]]
[:theme-name :string] [:set-name :string]
[:group :string] [:group? :boolean]
[:theme [:maybe ctob/schema:token-theme-attrs]]]]
[:set-tokens-lib ;; FIXME: we should not pass private types as part of changes
[:map {:title "SetTokensLib"} ;; protocol, the changes protocol should reflect a
[:type [:= :set-tokens-lib]] ;; method/protocol for perform surgical operations on file data,
[:tokens-lib ::sm/any]]] ;; this has nothing todo with internal types of a file data
;; structure.
[:token-set {:gen/gen (sg/generator ctob/schema:token-set)}
[:maybe [:fn ctob/token-set?]]]]]
[:set-token-set [:set-token
[:map {:title "SetTokenSetChange"} [:map {:title "SetTokenChange"}
[:type [:= :set-token-set]] [:type [:= :set-token]]
[:set-name :string] [:set-name :string]
[:group? :boolean] [:token-id ::sm/uuid]
[:token [:maybe ctob/schema:token-attrs]]]]
;; FIXME: we should not pass private types as part of changes [:set-base-font-size
;; protocol, the changes protocol should reflect a [:map {:title "ModBaseFontSize"}
;; method/protocol for perform surgical operations on file data, [:type [:= :set-base-font-size]]
;; this has nothing todo with internal types of a file data [:base-font-size :string]]]])
;; structure.
[:token-set {:gen/gen (sg/generator ctob/schema:token-set)}
[:maybe [:fn ctob/token-set?]]]]]
[:set-token
[:map {:title "SetTokenChange"}
[:type [:= :set-token]]
[:set-name :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])
(sm/register! ::change schema:change)
(sm/register! ::changes schema:changes)
(def valid-change? (def valid-change?
(sm/lazy-validator schema:change)) (sm/lazy-validator schema:change))
(def check-changes! (def check-changes
(sm/check-fn schema:changes)) (sm/check-fn schema:changes))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -534,7 +522,7 @@
;; When verify? false we spec the schema validation. Currently used ;; When verify? false we spec the schema validation. Currently used
;; to make just 1 validation even if the changes are applied twice ;; to make just 1 validation even if the changes are applied twice
(when verify? (when verify?
(check-changes! items)) (check-changes items))
(binding [*touched-changes* (volatile! #{}) (binding [*touched-changes* (volatile! #{})
cts/*wasm-sync* true] cts/*wasm-sync* true]
@ -547,11 +535,6 @@
#?(:clj (validate-shapes! data result items)) #?(:clj (validate-shapes! data result items))
result)))) result))))
;; DEPRECATED: remove after 2.3 release
(defmethod process-change :set-option
[data _]
data)
;; --- Comment Threads ;; --- Comment Threads
(defmethod process-change :set-comment-thread-position (defmethod process-change :set-comment-thread-position
@ -945,12 +928,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
@ -1091,21 +1068,23 @@
;; === Operations ;; === Operations
(def ^:private decode-shape (def decode-shape-attrs
(sm/decoder cts/schema:shape sm/json-transformer)) (sm/decoder cts/schema:shape-attrs sm/json-transformer))
(defmethod process-operation :assign (defmethod process-operation :assign
[{:keys [type] :as shape} {:keys [value] :as op}] [{:keys [type] :as shape} {:keys [value] :as op}]
(let [modifications (assoc value :type type) (let [modifications (assoc value :type type)
modifications (decode-shape modifications)] modifications (decode-shape-attrs modifications)]
(reduce-kv (fn [shape k v] (reduce-kv (fn [shape k v]
(process-operation shape {:type :set (if (not= v (get shape k))
:attr k (process-operation shape {:type :set
:val v :attr k
:ignore-touched (:ignore-touched op) :val v
:ignore-geometry (:ignore-geometry op)})) :ignore-touched (:ignore-touched op)
:ignore-geometry (:ignore-geometry op)})
shape))
shape shape
modifications))) (dissoc modifications :type))))
(defmethod process-operation :set (defmethod process-operation :set
[shape op] [shape op]

View File

@ -24,7 +24,7 @@
[app.common.uuid :as uuid])) [app.common.uuid :as uuid]))
;; Auxiliary functions to help create a set of changes (undo + redo) ;; Auxiliary functions to help create a set of changes (undo + redo)
;; TODO: this is a duplicate schema
(def schema:changes (def schema:changes
(sm/register! (sm/register!
^{::sm/type ::changes} ^{::sm/type ::changes}
@ -36,7 +36,7 @@
[:stack-undo? {:optional true} boolean?] [:stack-undo? {:optional true} boolean?]
[:undo-group {:optional true} ::sm/any]])) [:undo-group {:optional true} ::sm/any]]))
(def check-changes! (def check-changes
(sm/check-fn schema:changes)) (sm/check-fn schema:changes))
(defn empty-changes (defn empty-changes
@ -168,9 +168,8 @@
(defn apply-changes-local (defn apply-changes-local
[changes & {:keys [apply-to-library?]}] [changes & {:keys [apply-to-library?]}]
(assert (assert (check-changes changes)
(check-changes! changes) "expected valid changes")
"expected valid changes")
(if-let [file-data (::file-data (meta changes))] (if-let [file-data (::file-data (meta changes))]
(let [library-data (::library-data (meta changes)) (let [library-data (::library-data (meta changes))

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,41 @@
(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 [nname (namespace ref)
tname (name ref)
tname (str/capital (str/camel tname))
nname (cond
(or (= nname "app.common.schema")
(= nname "app.common.time")
(= nname "app.common.features"))
""
(= nname "datoteka.fs")
"Filesystem"
(str/starts-with? nname "app.common.geom")
(-> (str/replace nname #"app\.common\.geom\.\w+" "geom")
(str/camel)
(str/capital))
(str/starts-with? nname "app.")
(-> (subs nname 4)
(str/camel)
(str/capital))
:else
(str/capital (str/camel nname)))
rkey (str nname tname)]
(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,13 +135,13 @@
(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]
[:opacity {:optional true} [::sm/number {:min 0 :max 1}]] [:opacity {:optional true} [::sm/number {:min 0 :max 1}]]
[:modified-at {:optional true} ::ct/inst] [:modified-at {:optional true} ::ct/inst]
[:plugin-data {:optional true} ::ctpg/plugin-data]]) [:plugin-data {:optional true} ctpg/schema:plugin-data]])
(def schema:library-color (def schema:library-color
"Used for in-transit representation of a color (per example when user "Used for in-transit representation of a color (per example when user

View File

@ -19,19 +19,17 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def schema:component (def schema:component
(sm/register! [:merge
^{::sm/type ::component} [:map
[:merge [:id ::sm/uuid]
[:map [:name :string]
[:id ::sm/uuid] [:path {:optional true} [:maybe :string]]
[:name :string] [:modified-at {:optional true} ::ct/inst]
[:path {:optional true} [:maybe :string]] [:objects {:gen/max 10 :optional true} ctp/schema:objects]
[:modified-at {:optional true} ::ct/inst] [:main-instance-id ::sm/uuid]
[:objects {:gen/max 10 :optional true} ctp/schema:objects] [:main-instance-page ::sm/uuid]
[:main-instance-id ::sm/uuid] [:plugin-data {:optional true} ctpg/schema:plugin-data]]
[:main-instance-page ::sm/uuid] ctv/schema:variant-component])
[:plugin-data {:optional true} ctpg/schema:plugin-data]]
ctv/schema:variant-component]))
(def check-component (def check-component
(sm/check-fn schema:component)) (sm/check-fn schema:component))

View File

@ -110,7 +110,6 @@
(sm/register! ::data schema:data) (sm/register! ::data schema:data)
(sm/register! ::file schema:file) (sm/register! ::file schema:file)
(sm/register! ::media schema:media)
(sm/register! ::colors schema:colors) (sm/register! ::colors schema:colors)
(sm/register! ::typographies schema:typographies) (sm/register! ::typographies schema:typographies)

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,33 +37,28 @@
: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]]]])
(def schema:default-grids (def schema:default-grids
[:map {:title "PageGrid"} [:map {:title "PageGrid"}
[:square {:optional true} ::square-params] [:square {:optional true} schema:square-params]
[:row {:optional true} ::column-params] [:row {:optional true} schema:column-params]
[:column {:optional true} ::column-params]]) [:column {:optional true} schema:column-params]])
(sm/register! ::square-params schema:square-params)
(sm/register! ::column-params schema:column-params)
(sm/register! ::grid schema:grid)
(sm/register! ::default-grids schema:default-grids)
(def ^:private default-square-params (def ^:private default-square-params
{:size 16 {:size 16

View File

@ -40,7 +40,7 @@
[:map-of {:gen/max 2} ::sm/uuid schema:guide]) [:map-of {:gen/max 2} ::sm/uuid schema:guide])
(def schema:objects (def schema:objects
[:map-of {:gen/max 5} ::sm/uuid ::cts/shape]) [:map-of {:gen/max 5} ::sm/uuid cts/schema:shape])
(def schema:comment-thread-position (def schema:comment-thread-position
[:map {:title "CommentThreadPosition"} [:map {:title "CommentThreadPosition"}
@ -62,11 +62,6 @@
[:comment-thread-positions {:optional true} [:comment-thread-positions {:optional true}
[:map-of ::sm/uuid schema:comment-thread-position]]]) [:map-of ::sm/uuid schema:comment-thread-position]]])
(sm/register! ::objects schema:objects)
(sm/register! ::page schema:page)
(sm/register! ::guide schema:guide)
(sm/register! ::flow schema:flow)
(def valid-guide? (def valid-guide?
(sm/lazy-validator schema:guide)) (sm/lazy-validator schema:guide))

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

@ -6,7 +6,6 @@
(ns app.common.types.plugins (ns app.common.types.plugins
(:require (:require
[app.common.schema :as sm]
[app.common.schema.generators :as sg])) [app.common.schema.generators :as sg]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -22,13 +21,11 @@
:keyword]) :keyword])
(def schema:plugin-data (def schema:plugin-data
(sm/register! [:map-of {:gen/max 5 :title "PluginsData"}
^{::sm/type ::plugin-data} schema:keyword
[:map-of {:gen/max 5} [:map-of {:gen/max 5}
schema:keyword schema:string
[:map-of {:gen/max 5} schema:string]])
schema:string
schema:string]]))
(def ^:private schema:registry-entry (def ^:private schema:registry-entry
[:map [:map
@ -47,6 +44,3 @@
[:map-of {:gen/max 5} [:map-of {:gen/max 5}
:string :string
schema:registry-entry]]]) schema:registry-entry]]])
(sm/register! ::plugin-registry schema:plugin-registry)
(sm/register! ::registry-entry schema:registry-entry)

View File

@ -119,8 +119,6 @@
(def schema:points (def schema:points
[:vector {:gen/max 4 :gen/min 4} ::gpt/point]) [:vector {:gen/max 4 :gen/min 4} ::gpt/point])
;; FIXME: the register is necessary until this is moved to a separated
;; ns because it is used on shapes.text
(def valid-stroke-attrs (def valid-stroke-attrs
"A set used for proper check if color should contain only one of the "A set used for proper check if color should contain only one of the
attrs listed in this set." attrs listed in this set."
@ -156,10 +154,8 @@
(sm/keys schema:stroke-attrs)) (sm/keys schema:stroke-attrs))
(def schema:stroke (def schema:stroke
(sm/register! [:and schema:stroke-attrs
^{::sm/type ::stroke} [:fn has-valid-stroke-attrs?]])
[:and schema:stroke-attrs
[:fn has-valid-stroke-attrs?]]))
(def check-stroke (def check-stroke
(sm/check-fn schema:stroke)) (sm/check-fn schema:stroke))
@ -184,7 +180,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]
@ -213,22 +209,22 @@
[:r4 {:optional true} ::sm/safe-number] [:r4 {:optional true} ::sm/safe-number]
[:opacity {:optional true} ::sm/safe-number] [:opacity {:optional true} ::sm/safe-number]
[:grids {:optional true} [:grids {:optional true}
[:vector {:gen/max 2} ::ctg/grid]] [:vector {:gen/max 2} ctg/schema:grid]]
[:exports {:optional true} [:exports {:optional true}
[:vector {:gen/max 2} ::ctse/export]] [:vector {:gen/max 2} ctse/schema:export]]
[:strokes {:optional true} [:strokes {:optional true}
[:vector {:gen/max 2} schema:stroke]] [:vector {:gen/max 2} schema:stroke]]
[:blend-mode {:optional true} [:blend-mode {:optional true}
[::sm/one-of blend-modes]] [::sm/one-of blend-modes]]
[:interactions {:optional true} [:interactions {:optional true}
[:vector {:gen/max 2} ::ctsi/interaction]] [:vector {:gen/max 2} ctsi/schema:interaction]]
[:shadow {:optional true} [:shadow {:optional true}
[:vector {:gen/max 1} ctss/schema:shadow]] [:vector {:gen/max 1} ctss/schema:shadow]]
[:blur {:optional true} ::ctsb/blur] [:blur {:optional true} ctsb/schema:blur]
[:grow-type {:optional true} [:grow-type {:optional true}
[::sm/one-of grow-types]] [::sm/one-of grow-types]]
[:applied-tokens {:optional true} cto/schema:applied-tokens] [:applied-tokens {:optional true} cto/schema:applied-tokens]
[:plugin-data {:optional true} ::ctpg/plugin-data]]) [:plugin-data {:optional true} ctpg/schema:plugin-data]])
(def schema:group-attrs (def schema:group-attrs
[:map {:title "GroupAttrs"} [:map {:title "GroupAttrs"}
@ -274,7 +270,8 @@
(def ^:private schema:text-attrs (def ^:private schema:text-attrs
[:map {:title "TextAttrs"} [:map {:title "TextAttrs"}
[:content {:optional true} [:maybe ::ctsx/content]]]) [:position-data {:optional true} [:maybe ctsx/schema:position-data]]
[:content {:optional true} [:maybe ctsx/schema:content]]])
(defn- decode-shape (defn- decode-shape
[o] [o]
@ -326,8 +323,8 @@
schema:shape-generic-attrs schema:shape-generic-attrs
schema:shape-geom-attrs schema:shape-geom-attrs
schema:shape-base-attrs schema:shape-base-attrs
::ctv/variant-shape ctv/schema:variant-shape
::ctv/variant-container]] ctv/schema:variant-container]]
[:bool [:bool
[:merge {:title "BoolShape"} [:merge {:title "BoolShape"}
@ -384,13 +381,11 @@
schema:shape-base-attrs]]]) schema:shape-base-attrs]]])
(def schema:shape (def schema:shape
(sm/register! [:and {:title "Shape"
^{::sm/type ::shape} :gen/gen (shape-generator)
[:and {:title "Shape" :decode/json {:leave decode-shape}}
:gen/gen (shape-generator) [:fn shape?]
:decode/json {:leave decode-shape}} schema:shape-attrs])
[:fn shape?]
schema:shape-attrs]))
(def check-shape-generic-attrs (def check-shape-generic-attrs
(sm/check-fn schema:shape-generic-attrs)) (sm/check-fn schema:shape-generic-attrs))

View File

@ -6,30 +6,11 @@
(ns app.common.types.shape.blur (ns app.common.types.shape.blur
(:require (:require
[app.common.schema :as sm] [app.common.schema :as sm]))
[app.common.spec :as us]
[clojure.spec.alpha :as s]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (def schema:blur
;; SPEC [:map {:title "Blur"}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; [:id ::sm/uuid]
[:type [:= :layer-blur]]
(s/def ::id uuid?) [:value ::sm/safe-number]
(s/def ::type #{:layer-blur}) [:hidden :boolean]])
(s/def ::value ::us/safe-number)
(s/def ::hidden boolean?)
(s/def ::blur
(s/keys :req-un [::id ::type ::value ::hidden]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SCHEMA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(sm/register!
^{::sm/type ::blur}
[:map {:title "Blur"}
[:id ::sm/uuid]
[:type [:= :layer-blur]]
[:value ::sm/safe-number]
[:hidden :boolean]])

View File

@ -15,5 +15,3 @@
[:type [::sm/one-of types]] [:type [::sm/one-of types]]
[:scale ::sm/safe-number] [:scale ::sm/safe-number]
[:suffix :string]]) [:suffix :string]])
(sm/register! ::export schema:export)

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,34 +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)
(def check-interaction (def check-interaction
(sm/check-fn schema:interaction)) (sm/check-fn 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

@ -7,9 +7,7 @@
(ns app.common.types.shape.text (ns app.common.types.shape.text
(:require (:require
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.types.fills :refer [schema:fill]] [app.common.types.fills :refer [schema:fill]]))
[app.common.types.shape :as-alias shape]
[app.common.types.shape.text.position-data :as-alias position-data]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SCHEMA ;; SCHEMA
@ -63,26 +61,22 @@
[:typography-ref-id {:optional true} [:maybe ::sm/uuid]] [:typography-ref-id {:optional true} [:maybe ::sm/uuid]]
[:typography-ref-file {:optional true} [:maybe ::sm/uuid]]]]]]]]]]]]]) [:typography-ref-file {:optional true} [:maybe ::sm/uuid]]]]]]]]]]]]])
(sm/register! ::content schema:content)
(def valid-content? (def valid-content?
(sm/lazy-validator schema:content)) (sm/lazy-validator schema:content))
(sm/register! (def schema:position-data
^{::sm/type ::position-data} [:vector {:min 1 :gen/max 2}
[:vector {:min 1 :gen/max 2} [:map
[:map [:x ::sm/safe-number]
[:x ::sm/safe-number] [:y ::sm/safe-number]
[:y ::sm/safe-number] [:width ::sm/safe-number]
[:width ::sm/safe-number] [:height ::sm/safe-number]
[:height ::sm/safe-number] [:fills [:vector {:gen/max 2} schema:fill]]
[:fills [:vector {:gen/max 2} schema:fill]] [:font-family {:optional true} :string]
[:font-family {:optional true} :string] [:font-size {:optional true} :string]
[:font-size {:optional true} :string] [:font-style {:optional true} :string]
[:font-style {:optional true} :string] [:font-weight {:optional true} :string]
[:font-weight {:optional true} :string] [:rtl {:optional true} :boolean]
[:rtl {:optional true} :boolean] [:text {:optional true} :string]
[:text {:optional true} :string] [:text-decoration {:optional true} :string]
[:text-decoration {:optional true} :string] [:text-transform {:optional true} :string]]])
[:text-transform {:optional true} :string]]])

View File

@ -17,4 +17,5 @@
:admin {:can-edit true :is-admin true :is-owner false} :admin {:can-edit true :is-admin true :is-owner false}
:owner {:can-edit true :is-admin true :is-owner true}}) :owner {:can-edit true :is-admin true :is-owner true}})
(sm/register! ::role [::sm/one-of valid-roles]) (def schema:role
[::sm/one-of {:title "TeamRole"} valid-roles])

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

View File

@ -543,18 +543,17 @@
(get-ordered-set-names [_] "get an ordered sequence of all sets names in the library") (get-ordered-set-names [_] "get an ordered sequence of all sets names in the library")
(get-set [_ set-name] "get one set looking for name")) (get-set [_ set-name] "get one set looking for name"))
(def schema:token-set-node (def ^:private schema:token-set-node
[:schema {:registry {::node [:or [:fn token-set?] [:schema {:registry {::node
[:and [:or [:fn token-set?]
[:map-of {:gen/max 5} :string [:ref ::node]] [:and
[:fn d/ordered-map?]]]}} [:map-of {:gen/max 5} :string [:ref ::node]]
[:fn d/ordered-map?]]]}}
[:ref ::node]]) [:ref ::node]])
(def schema:token-sets (def ^:private schema:token-sets
[:and [:and {:title "TokenSets"}
[:map-of {:title "TokenSets"} [:map-of :string schema:token-set-node]
:string
schema:token-set-node]
[:fn d/ordered-map?]]) [:fn d/ordered-map?]])
(def ^:private check-token-sets (def ^:private check-token-sets
@ -1375,7 +1374,7 @@ Will return a value that matches this schema:
(or tokens-lib (make-tokens-lib))) (or tokens-lib (make-tokens-lib)))
(def schema:tokens-lib (def schema:tokens-lib
(sm/register! (sm/type-schema
{:type ::tokens-lib {:type ::tokens-lib
:pred valid-tokens-lib? :pred valid-tokens-lib?
:type-properties :type-properties

View File

@ -18,26 +18,24 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def schema:typography (def schema:typography
(sm/register! [:map {:title "Typography"}
^{::sm/type ::typography} [:id ::sm/uuid]
[:map {:title "Typography"} [:name :string]
[:id ::sm/uuid] [:font-id :string]
[:name :string] [:font-family :string]
[:font-id :string] [:font-variant-id :string]
[:font-family :string] [:font-size :string]
[:font-variant-id :string] [:font-weight :string]
[:font-size :string] [:font-style :string]
[:font-weight :string] [:line-height :string]
[:font-style :string] [:letter-spacing :string]
[:line-height :string] [:text-transform :string]
[:letter-spacing :string] [:modified-at {:optional true} ::ct/inst]
[:text-transform :string] [:path {:optional true} [:maybe :string]]
[:modified-at {:optional true} ::ct/inst] [:plugin-data {:optional true} ctpg/schema:plugin-data]])
[:path {:optional true} [:maybe :string]]
[:plugin-data {:optional true} ::ctpg/plugin-data]]))
(def check-typography (def check-typography
(sm/check-fn ::typography)) (sm/check-fn schema:typography))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; HELPERS ;; HELPERS

View File

@ -22,34 +22,27 @@
[:value :string]]) [:value :string]])
(def schema:variant-component (def schema:variant-component
;; A component that is part of a variant set. "A component that is part of a variant set"
(sm/register! [:map
^{::sm/type ::variant-component} [:variant-id {:optional true} ::sm/uuid]
[:map [:variant-properties {:optional true} [:vector schema:variant-property]]])
[:variant-id {:optional true} ::sm/uuid]
[:variant-properties {:optional true} [:vector schema:variant-property]]]))
(def schema:variant-shape (def schema:variant-shape
;; The root shape of the main instance of a variant component. "The root shape of the main instance of a variant component"
[:map [:map
[:variant-id {:optional true} ::sm/uuid] [:variant-id {:optional true} ::sm/uuid]
[:variant-name {:optional true} :string] [:variant-name {:optional true} :string]
[:variant-error {:optional true} :string]]) [:variant-error {:optional true} :string]])
(def schema:variant-container (def schema:variant-container
;; is a board that contains all variant components of a variant set, "Is a board that contains all variant components of a variant set,
;; for grouping them visually in the workspace. for grouping them visually in the workspace"
[:map [:map
[:is-variant-container {:optional true} :boolean]]) [:is-variant-container {:optional true} :boolean]])
(sm/register! ::variant-property schema:variant-property)
(sm/register! ::variant-shape schema:variant-shape)
(sm/register! ::variant-container schema:variant-container)
(def valid-variant-component? (def valid-variant-component?
(sm/check-fn schema:variant-component)) (sm/check-fn schema:variant-component))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def property-prefix "Property ") (def property-prefix "Property ")

View File

@ -14,7 +14,7 @@
[app.common.types.color :refer [schema:color schema:gradient]] [app.common.types.color :refer [schema:color schema:gradient]]
[app.common.types.path :as path] [app.common.types.path :as path]
[app.common.types.plugins :refer [schema:plugin-data]] [app.common.types.plugins :refer [schema:plugin-data]]
[app.common.types.shape :as tsh] [app.common.types.shape :as tsh :refer [schema:shape]]
[app.common.types.shape.interactions :refer [schema:animation schema:interaction]] [app.common.types.shape.interactions :refer [schema:animation schema:interaction]]
[app.common.types.shape.shadow :refer [schema:shadow]] [app.common.types.shape.shadow :refer [schema:shadow]]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
@ -135,10 +135,10 @@
{:num 500}))) {:num 500})))
(t/deftest shape-json-roundtrip (t/deftest shape-json-roundtrip
(let [encode (sm/encoder ::tsh/shape (sm/json-transformer)) (let [encode (sm/encoder schema:shape (sm/json-transformer))
decode (sm/decoder ::tsh/shape (sm/json-transformer))] decode (sm/decoder schema:shape (sm/json-transformer))]
(smt/check! (smt/check!
(smt/for [shape (sg/generator ::tsh/shape)] (smt/for [shape (sg/generator schema:shape)]
(let [shape-1 (encode shape) (let [shape-1 (encode shape)
shape-2 (json-roundtrip shape-1) shape-2 (json-roundtrip shape-1)
shape-3 (decode shape-2)] shape-3 (decode shape-2)]

View File

@ -7,7 +7,6 @@
(ns app.main.data.changes (ns app.main.data.changes
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.changes :as cpc] [app.common.files.changes :as cpc]
[app.common.logging :as log] [app.common.logging :as log]
[app.common.time :as ct] [app.common.time :as ct]
@ -106,13 +105,11 @@
[{:keys [commit-id redo-changes undo-changes origin save-undo? features [{:keys [commit-id redo-changes undo-changes origin save-undo? features
file-id file-revn file-vern undo-group tags stack-undo? source]}] file-id file-revn file-vern undo-group tags stack-undo? source]}]
(dm/assert! (assert (cpc/check-changes redo-changes)
"expect valid vector of changes for redo-changes" "expect valid vector of changes for redo-changes")
(cpc/check-changes! redo-changes))
(dm/assert! (assert (cpc/check-changes undo-changes)
"expect valid vector of changes for undo-changes" "expect valid vector of changes for undo-changes")
(cpc/check-changes! undo-changes))
(let [commit-id (or commit-id (uuid/next)) (let [commit-id (or commit-id (uuid/next))
source (d/nilv source :local) source (d/nilv source :local)

View File

@ -760,13 +760,11 @@
(defn ext-library-changed (defn ext-library-changed
[library-id modified-at revn changes] [library-id modified-at revn changes]
(dm/assert! (assert (uuid? library-id)
"expected valid uuid for library-id" "expected valid uuid for library-id")
(uuid? library-id))
(dm/assert! (assert (ch/check-changes changes)
"expected valid changes vector" "expected valid changes vector")
(ch/check-changes! changes))
(ptk/reify ::ext-library-changed (ptk/reify ::ext-library-changed
ptk/UpdateEvent ptk/UpdateEvent

View File

@ -236,7 +236,7 @@
[:session-id ::sm/uuid] [:session-id ::sm/uuid]
[:revn :int] [:revn :int]
[:vern :int] [:vern :int]
[:changes ::cpc/changes]]) [:changes cpc/schema:changes]])
(def ^:private check-file-change-params! (def ^:private check-file-change-params!
(sm/check-fn schema:handle-file-change)) (sm/check-fn schema:handle-file-change))
@ -279,9 +279,8 @@
(defn handle-file-restore (defn handle-file-restore
[{:keys [file-id vern] :as msg}] [{:keys [file-id vern] :as msg}]
(dm/assert! (assert (check-file-restore-params msg)
"expected valid parameters" "expected valid parameters")
(check-file-restore-params msg))
(ptk/reify ::handle-file-restore (ptk/reify ::handle-file-restore
ptk/WatchEvent ptk/WatchEvent
@ -302,16 +301,15 @@
[:session-id ::sm/uuid] [:session-id ::sm/uuid]
[:revn :int] [:revn :int]
[:modified-at ::ct/inst] [:modified-at ::ct/inst]
[:changes ::cpc/changes]]) [:changes cpc/schema:changes]])
(def ^:private check-library-change-params! (def ^:private check-library-change-params
(sm/check-fn schema:handle-library-change)) (sm/check-fn schema:handle-library-change))
(defn handle-library-change (defn handle-library-change
[{:keys [file-id modified-at changes revn] :as msg}] [{:keys [file-id modified-at changes revn] :as msg}]
(dm/assert! (assert (check-library-change-params msg)
"expected valid arguments" "expected valid arguments")
(check-library-change-params! msg))
(ptk/reify ::handle-library-change (ptk/reify ::handle-library-change
ptk/WatchEvent ptk/WatchEvent

View File

@ -57,8 +57,8 @@
(def ^:private (def ^:private
schema:undo-entry schema:undo-entry
[:map {:title "undo-entry"} [:map {:title "undo-entry"}
[:undo-changes [:vector ::cpc/change]] [:undo-changes [:vector cpc/schema:change]]
[:redo-changes [:vector ::cpc/change]] [:redo-changes [:vector cpc/schema:change]]
[:undo-group ::sm/uuid] [:undo-group ::sm/uuid]
[:tags [:set :keyword]]]) [:tags [:set :keyword]]])

View File

@ -119,7 +119,7 @@
(-> (u/proxy->interaction self) (-> (u/proxy->interaction self)
(d/patch-object params))] (d/patch-object params))]
(cond (cond
(not (sm/validate ::ctsi/interaction interaction)) (not (sm/validate ctsi/schema:interaction interaction))
(u/display-not-valid :action interaction) (u/display-not-valid :action interaction)
:else :else
@ -453,7 +453,7 @@
(let [id (obj/get self "$id") (let [id (obj/get self "$id")
value (blur-defaults (parser/parse-blur value))] value (blur-defaults (parser/parse-blur value))]
(cond (cond
(not (sm/validate ::ctsb/blur value)) (not (sm/validate ctsb/schema:blur value))
(u/display-not-valid :blur value) (u/display-not-valid :blur value)
(not (r/check-permission plugin-id "content:write")) (not (r/check-permission plugin-id "content:write"))
@ -470,7 +470,7 @@
(let [id (obj/get self "$id") (let [id (obj/get self "$id")
value (parser/parse-exports value)] value (parser/parse-exports value)]
(cond (cond
(not (sm/validate [:vector ::ctse/export] value)) (not (sm/validate [:vector ctse/schema:export] value))
(u/display-not-valid :exports value) (u/display-not-valid :exports value)
(not (r/check-permission plugin-id "content:write")) (not (r/check-permission plugin-id "content:write"))
@ -1129,7 +1129,7 @@
(fn [value] (fn [value]
(let [value (parser/parse-export value)] (let [value (parser/parse-export value)]
(cond (cond
(not (sm/validate ::ctse/export value)) (not (sm/validate ctse/schema:export value))
(u/display-not-valid :export value) (u/display-not-valid :export value)
:else :else
@ -1161,7 +1161,7 @@
(-> ctsi/default-interaction (-> ctsi/default-interaction
(d/patch-object (parser/parse-interaction trigger action delay)))] (d/patch-object (parser/parse-interaction trigger action delay)))]
(cond (cond
(not (sm/validate ::ctsi/interaction interaction)) (not (sm/validate ctsi/schema:interaction interaction))
(u/display-not-valid :addInteraction interaction) (u/display-not-valid :addInteraction interaction)
:else :else

View File

@ -54,7 +54,7 @@
(sm/encoder types.tokens-lib/schema:tokens-lib sm/json-transformer)) (sm/encoder types.tokens-lib/schema:tokens-lib sm/json-transformer))
(def encode-plugin-data (def encode-plugin-data
(sm/encoder ::ctpg/plugin-data sm/json-transformer)) (sm/encoder ctpg/schema:plugin-data sm/json-transformer))
(def ^:private valid-buckets (def ^:private valid-buckets
#{"file-media-object" #{"file-media-object"