|
|
@@ -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]]
|