diff --git a/.clj-kondo/metosin/malli-types/config.edn b/.clj-kondo/metosin/malli-types/config.edn new file mode 100644 index 0000000000..ebdd7c5def --- /dev/null +++ b/.clj-kondo/metosin/malli-types/config.edn @@ -0,0 +1,23 @@ +{:linters + {:unresolved-symbol {:exclude [(malli.core/=>)]}, + :type-mismatch + {:namespaces + {frontend.util + {safe-re-find {:arities {2 {:args [:any :string], :ret :any}}}, + check-password-strength + {:arities + {1 + {:args [:string], + :ret + {:op :keys, + :req + {:contains :sequential, + :length :int, + :id :int, + :value :string}, + :nilable true}}}}, + uuid-string? {:arities {1 {:args [:string], :ret :boolean}}}, + safe-parse-int {:arities {1 {:args [:any], :ret :int}}}, + safe-sanitize-file-name + {:arities {1 {:args [:string], :ret :string}}}, + safe-parse-float {:arities {1 {:args [:any], :ret :double}}}}}}}} diff --git a/bb.edn b/bb.edn index f812107834..444bedc333 100644 --- a/bb.edn +++ b/bb.edn @@ -69,6 +69,9 @@ dev:lint logseq.tasks.dev/lint + dev:gen-malli-kondo-config + logseq.tasks.dev/gen-malli-kondo-config + lint:large-vars logseq.bb-tasks.lint.large-vars/-main diff --git a/deps.edn b/deps.edn index ad55898614..a1960cf714 100755 --- a/deps.edn +++ b/deps.edn @@ -1,6 +1,6 @@ {:paths ["src/main" "src/electron" "templates"] :deps - {org.clojure/clojure {:mvn/version "1.10.0"} + {org.clojure/clojure {:mvn/version "1.11.1"} rum/rum {:mvn/version "0.12.9"} datascript/datascript {:mvn/version "1.3.8"} datascript-transit/datascript-transit {:mvn/version "0.3.0"} @@ -19,7 +19,7 @@ org.clj-commons/hickory {:mvn/version "0.7.3"} hiccups/hiccups {:mvn/version "0.3.0"} tongue/tongue {:mvn/version "0.4.4"} - org.clojure/core.async {:mvn/version "1.3.610"} + org.clojure/core.async {:mvn/version "1.6.673"} thheller/shadow-cljs {:mvn/version "2.19.0"} expound/expound {:mvn/version "0.8.6"} com.lambdaisland/glogi {:mvn/version "1.1.144"} @@ -32,7 +32,6 @@ :aliases {:cljs {:extra-paths ["src/dev-cljs/" "src/test/" "src/electron/"] :extra-deps {org.clojure/clojurescript {:mvn/version "1.11.54"} - org.clojure/tools.namespace {:mvn/version "0.2.11"} cider/cider-nrepl {:mvn/version "0.28.4"} org.clojars.knubie/cljs-run-test {:mvn/version "1.0.1"}} :main-opts ["-m" "shadow.cljs.devtools.cli"]} diff --git a/scripts/src/logseq/tasks/dev.clj b/scripts/src/logseq/tasks/dev.clj index 998b6dc1ca..c6b7c98959 100644 --- a/scripts/src/logseq/tasks/dev.clj +++ b/scripts/src/logseq/tasks/dev.clj @@ -1,7 +1,10 @@ (ns logseq.tasks.dev "Tasks for general development. For desktop or mobile development see their namespaces" - (:require [babashka.tasks :refer [shell]])) + (:require [babashka.tasks :refer [shell]] + [clojure.java.io :as io] + [clojure.pprint :as pp] + [clojure.edn :as edn])) (defn lint "Run all lint tasks @@ -17,3 +20,18 @@ "bb lint:ns-docstrings"]] (println cmd) (shell cmd))) + + +(defn gen-malli-kondo-config + "Generate clj-kondo type-mismatch config from malli schema + .clj-kondo/metosin/malli-types/config.edn" + [] + (let [config-edn ".clj-kondo/metosin/malli-types/config.edn" + compile-cmd "clojure -M:cljs compile gen-malli-kondo-config"] + (println compile-cmd) + (shell compile-cmd) + (println "generate kondo config: " config-edn) + (io/make-parents config-edn) + (let [config (with-out-str + (pp/pprint (edn/read-string (:out (shell {:out :string} "node ./static/gen-malli-kondo-config.js")))))] + (spit config-edn config)))) diff --git a/shadow-cljs.edn b/shadow-cljs.edn index 0cf2e35d6b..7bfe14325d 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -75,6 +75,13 @@ :compiler-options {:static-fns false} :main frontend.test.frontend-node-test-runner/main} + :gen-malli-kondo-config {:target :node-script + :closure-defines {frontend.util/NODETEST true} + :devtools {:enabled false} + :compiler-options {:static-fns false} + :output-to "static/gen-malli-kondo-config.js" + :main gen-malli-kondo-config.core/main} + :publishing {:target :browser :module-loader true :js-options {:ignore-asset-requires true} diff --git a/src/main/frontend/core.cljs b/src/main/frontend/core.cljs index df316b27a0..ed72c77ee1 100644 --- a/src/main/frontend/core.cljs +++ b/src/main/frontend/core.cljs @@ -1,5 +1,6 @@ (ns frontend.core "Entry ns for the mobile, browser and electron frontend apps" + {:dev/always true} (:require [rum.core :as rum] [frontend.handler :as handler] [frontend.handler.plugin :as plugin-handler] @@ -13,7 +14,8 @@ [reitit.frontend.easy :as rfe] [logseq.api] [frontend.fs.sync :as sync] - [frontend.config :as config])) + [frontend.config :as config] + [malli.dev.cljs :as md])) (defn set-router! [] @@ -43,6 +45,8 @@ ")) (defn start [] + (when config/dev? + (md/start!)) (when-let [node (.getElementById js/document "root")] (set-router!) (rum/mount (page/current-page) node) @@ -64,5 +68,6 @@ ;; this is controlled by :before-load in the config (handler/stop!) (when config/dev? - (sync/ [:cat :any :string] [:or :nil :string [:vector [:maybe :string]]]]} [pattern s] (when-not (string? s) ;; TODO: sentry @@ -70,16 +71,27 @@ (def uuid-pattern "[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}") (defonce exactly-uuid-pattern (re-pattern (str "(?i)^" uuid-pattern "$"))) (defn uuid-string? + {:malli/schema [:=> [:cat :string] :boolean]} [s] - (safe-re-find exactly-uuid-pattern s)) - (defn check-password-strength [input] + (boolean (safe-re-find exactly-uuid-pattern s))) + (defn check-password-strength + {:malli/schema [:=> [:cat :string] [:maybe + [:map + [:contains [:sequential :string]] + [:length :int] + [:id :int] + [:value :string]]]]} + [input] (when-let [^js ret (and (string? input) (not (string/blank? input)) (passwordStrength input))] (bean/->clj ret))) - (defn safe-sanitize-file-name [s] + (defn safe-sanitize-file-name + {:malli/schema [:=> [:cat :string] :string]} + [s] (sanitizeFilename (str s))))) + #?(:cljs (do (defn- ios*? @@ -248,9 +260,11 @@ (str "0" n) (str n))) + #?(:cljs (defn safe-parse-int "Use if arg could be an int or string. If arg is only a string, use `parse-long`." + {:malli/schema [:=> [:cat [:or :int :string]] :int]} [x] (if (string? x) (parse-long x) @@ -259,11 +273,13 @@ #?(:cljs (defn safe-parse-float "Use if arg could be a float or string. If arg is only a string, use `parse-double`" + {:malli/schema [:=> [:cat [:or :double :string]] :double]} [x] (if (string? x) (parse-double x) x))) + #?(:cljs (defn debounce "Returns a function that will call f only after threshold has passed without new calls diff --git a/src/main/gen_malli_kondo_config/collect.clj b/src/main/gen_malli_kondo_config/collect.clj new file mode 100644 index 0000000000..74a951a677 --- /dev/null +++ b/src/main/gen_malli_kondo_config/collect.clj @@ -0,0 +1,8 @@ +(ns gen-malli-kondo-config.collect + (:require [cljs.analyzer.api :as ana-api])) + + + +(defmacro collect-schema + [] + `(malli.instrument/collect! {:ns ~(vec (ana-api/all-ns))})) diff --git a/src/main/gen_malli_kondo_config/core.cljs b/src/main/gen_malli_kondo_config/core.cljs new file mode 100644 index 0000000000..51c7f50ce9 --- /dev/null +++ b/src/main/gen_malli_kondo_config/core.cljs @@ -0,0 +1,12 @@ +(ns gen-malli-kondo-config.core + (:require-macros [gen-malli-kondo-config.collect :refer [collect-schema]]) + (:require [frontend.util] + [frontend.util.list] + [malli.clj-kondo :as mc] + [malli.dev.cljs :as md])) + + +(defn main [& _args] + (collect-schema) + (println (mc/linter-config (mc/collect-cljs))) + (js/process.exit 0))