Browse Source

enhance: ident validation

block properties and class idents now have specific validation.
Also cleaned up overlapping ident definitions and updated incorrect
docstrings
Gabriel Horner 1 năm trước cách đây
mục cha
commit
14a3e5287b
1 tập tin đã thay đổi với 58 bổ sung41 xóa
  1. 58 41
      deps/db/src/logseq/db/frontend/malli_schema.cljs

+ 58 - 41
deps/db/src/logseq/db/frontend/malli_schema.cljs

@@ -7,6 +7,55 @@
             [datascript.core :as d]
             [logseq.db.frontend.property :as db-property]))
 
+;; :db/ident malli schemas
+;; =======================
+
+(def logseq-property-namespaces
+  #{"logseq.property" "logseq.property.table" "logseq.property.tldraw"
+    "logseq.task"})
+
+(def db-attribute-properties
+  "Internal properties that are also db attributes"
+  #{:block/alias :block/tags})
+
+(def db-attribute-ident
+  (into [:enum] db-attribute-properties))
+
+(def logseq-property-ident
+  [:and :keyword [:fn
+                  {:error/message "should be a valid logseq property namespace"}
+                  (fn logseq-namespace? [k]
+                    (contains? logseq-property-namespaces (namespace k)))]])
+
+(def internal-property-ident
+  [:or logseq-property-ident db-attribute-ident])
+
+(defn user-property-namespace?
+  "Determines if keyword is a user property"
+  [kw]
+  (contains? #{"user.property"} (namespace kw)))
+
+(def user-property-ident
+  [:and :keyword [:fn
+                  {:error/message "should be a valid user property namespace"}
+                  user-property-namespace?]])
+
+(def property-ident
+  [:or internal-property-ident user-property-ident])
+
+(def logseq-ident-namespaces
+  "Set of all namespaces Logseq uses for :db/ident except for
+  db-attribute-ident. It's important to grow this list purposefully and have it
+  start with 'logseq' to allow for users and 3rd party plugins to provide their
+  own namespaces to core concepts."
+  (into logseq-property-namespaces #{"logseq.class" "logseq.kv"}))
+
+(def logseq-ident
+  [:and :keyword [:fn
+                  {:error/message "should be a valid :db/ident namespace"}
+                  (fn logseq-namespace? [k]
+                    (contains? logseq-ident-namespaces (namespace k)))]])
+
 ;; Helper fns
 ;; ==========
 (defn- validate-property-value
@@ -30,8 +79,7 @@
                        (let [[property-type schema-fn] e
                              schema-fn' (if (db-property-type/property-types-with-db property-type) (partial schema-fn db) schema-fn)
                              validation-fn #(validate-property-value property-type schema-fn' %)]
-                         ;; TODO: Be more specific about :keyword
-                         [property-type [:tuple :keyword [:fn validation-fn]]])
+                         [property-type [:tuple property-ident [:fn validation-fn]]])
                        :else
                        e)))
                  db-schema))
@@ -59,8 +107,8 @@
                    (update acc (:e m) assoc (:a m) (:v m))))
                {})))
 
-;; Malli schemas
-;; =============
+;; Main malli schemas
+;; ==================
 ;; These schemas should be data vars to remain as simple and reusable as possible
 (def property-tuple
   "Represents a tuple of a property and its property value. This schema
@@ -102,37 +150,6 @@
     ;; TODO: Should this be here or in common?
    [:block/path-refs {:optional true} [:set :int]]])
 
-(def logseq-ident-namespaces
-  "Set of all namespaces Logseq uses for :db/ident. It's important to grow this
-  list purposefully and have it start with 'logseq' to allow for users and 3rd
-  party plugins to provide their own namespaces to core concepts."
-  #{"logseq.property" "logseq.property.table" "logseq.property.tldraw"
-    "logseq.class" "logseq.task" "logseq.kv"})
-
-(def user-ident-namespaces
-  "Set of all namespaces Logseq uses for :db/ident. It's important to grow this
-  list purposefully and have it start with 'logseq' to allow for users and 3rd
-  party plugins to provide their own namespaces to core concepts."
-  #{"user.property"})
-
-(def db-attribute
-  [:and :keyword [:fn
-                  {:error/message "should be a valid db attribute"}
-                  (fn db-attribute? [k]
-                    (contains? #{"block"} (namespace k)))]])
-
-(def logseq-ident
-  [:and :keyword [:fn
-                  {:error/message "should be a valid :db/ident namespace"}
-                  (fn logseq-namespace? [k]
-                    (contains? logseq-ident-namespaces (namespace k)))]])
-
-(def user-ident
-  [:and :keyword [:fn
-                  {:error/message "should be a valid :db/ident namespace"}
-                  (fn user-namespace? [k]
-                    (contains? user-ident-namespaces (namespace k)))]])
-
 (def property-attrs
   "Common attributes for properties"
   [[:db/index {:optional true} :boolean]
@@ -151,7 +168,7 @@
     page-or-block-attrs)))
 
 (def class-attrs
-  [[:db/ident {:optional true} :keyword]
+  [[:db/ident {:optional true} logseq-ident]
    [:class/parent {:optional true} :int]
    [:class/schema.properties {:optional true} [:set :int]]])
 
@@ -187,7 +204,7 @@
   (vec
    (concat
     [:map
-     [:db/ident [:or logseq-ident db-attribute]]
+     [:db/ident internal-property-ident]
      [:block/schema
       (vec
        (concat
@@ -222,7 +239,7 @@
   (vec
    (concat
     [:map
-     [:db/ident user-ident]
+     [:db/ident user-property-ident]
      [:block/schema {:optional true} user-property-schema]]
     property-attrs
     page-attrs
@@ -230,8 +247,8 @@
 
 (def property-page
   [:multi {:dispatch (fn [m]
-                       (or (string/starts-with? (namespace (m :db/ident)) "logseq.")
-                           (= "block" (namespace (m :db/ident)))))}
+                       (or (contains? logseq-property-namespaces (namespace (m :db/ident)))
+                           (contains? db-attribute-properties (m :db/ident))))}
    [true internal-property]
    [:malli.core/default user-property]])
 
@@ -285,7 +302,7 @@
     [:map]
     [[:block/type [:= #{"closed value"}]]
      ;; for built-in properties
-     [:db/ident {:optional true} logseq-ident]
+     [:db/ident {:optional true} logseq-property-ident]
      [:block/schema {:optional true}
       [:map
        [:value [:or :string :double]]