From a096b08e8cf24e8c3acfbc724381f92bdfc9497a Mon Sep 17 00:00:00 2001 From: caumond Date: Tue, 24 Oct 2023 19:35:08 +0200 Subject: [PATCH] init --- bb.edn | 170 +++++----- build_config.edn | 14 +- deps.edn | 80 ++--- docs/code/alias.edn | 2 + docs/code/comments.edn | 1 + docs/code/css.edn | 1 + docs/code/deps-ns.svg | 3 + docs/code/deps.png | 3 + docs/code/namespace.edn | 2 + env/development/resources/version.edn | 3 + .../src/clj/automaton_core/repl_core.clj | 17 +- src/clj/automaton_core/adapters/bb_edn.clj | 21 -- .../automaton_core/adapters/build_config.clj | 56 ++-- .../adapters/code_formatter.clj | 29 -- src/clj/automaton_core/adapters/commands.clj | 149 ++++----- src/clj/automaton_core/adapters/deps_edn.clj | 55 ++-- src/clj/automaton_core/adapters/edn_utils.clj | 98 +++--- .../automaton_core/adapters/env_variables.clj | 8 +- src/clj/automaton_core/adapters/files.clj | 294 ++++++++---------- .../adapters/java_properties.clj | 12 +- src/clj/automaton_core/adapters/schema.clj | 17 +- src/clj/automaton_core/adapters/version.clj | 18 +- src/clj/automaton_core/configuration.clj | 62 ++-- .../automaton_core/configuration/edn_read.clj | 29 +- .../automaton_core/configuration/protocol.clj | 3 +- .../configuration/simple_files.clj | 16 +- src/clj/automaton_core/dev.clj | 21 +- src/clj/automaton_core/log/be_log.clj | 26 +- src/clj/automaton_core/log/be_registry.clj | 31 +- src/clj/automaton_core/log/impl/log4j2.clj | 10 +- src/clj/automaton_core/log/log4j2.clj | 24 +- .../log/tracking/be_error_tracking.clj | 29 +- .../automaton_core/log/tracking/be_sentry.clj | 47 ++- src/clj/automaton_core/os/code_formatter.clj | 23 ++ src/clj/automaton_core/repl.clj | 68 ++-- src/clj/automaton_core/utils/date.clj | 12 +- src/clj/automaton_core/utils/pretty_print.clj | 10 +- src/cljc/automaton_core/adapters/re.cljc | 15 +- src/cljc/automaton_core/adapters/string.cljc | 38 +-- src/cljc/automaton_core/i18n/dict/text.cljc | 3 +- src/cljc/automaton_core/i18n/language.cljc | 59 ++-- .../i18n/missing_translation_report.cljc | 23 +- src/cljc/automaton_core/i18n/translator.cljc | 9 +- .../i18n/translator/tempura.cljc | 58 ++-- src/cljc/automaton_core/log.cljc | 218 ++++++++----- src/cljc/automaton_core/log/log_levels.cljc | 13 +- src/cljc/automaton_core/log/registry.cljc | 14 +- src/cljc/automaton_core/log/strategy.cljc | 6 +- .../log/strategy/static_ns_level.cljc | 62 ++-- .../automaton_core/log/tracking/sentry.cljc | 12 +- src/cljc/automaton_core/url.cljc | 27 +- src/cljc/automaton_core/utils/fallback.cljc | 19 +- src/cljc/automaton_core/utils/map.cljc | 116 +++---- src/cljc/automaton_core/utils/sequences.cljc | 17 +- .../automaton_core/utils/string_to_id.cljc | 5 +- src/cljc/automaton_core/utils/uuid_gen.cljc | 6 +- src/cljs/automaton_core/log/fe_log.cljc | 45 +-- src/cljs/automaton_core/log/fe_registry.cljc | 33 +- src/cljs/automaton_core/log/impl/print.cljs | 6 +- src/cljs/automaton_core/log/print.cljs | 6 +- .../log/tracking/fe_error_tracking.cljs | 30 +- .../log/tracking/fe_sentry.cljs | 59 ++-- .../automaton_core/adapters/bb_edn_test.clj | 39 --- .../adapters/build_config_test.clj | 5 + .../adapters/code_files_test.clj | 73 ----- .../adapters/code_formatter_test.clj | 18 -- .../automaton_core/utils/fallback_test.cljc | 6 - version.edn | 3 + 68 files changed, 1055 insertions(+), 1452 deletions(-) create mode 100644 docs/code/alias.edn create mode 100644 docs/code/comments.edn create mode 100644 docs/code/css.edn create mode 100644 docs/code/deps-ns.svg create mode 100644 docs/code/deps.png create mode 100644 docs/code/namespace.edn create mode 100644 env/development/resources/version.edn delete mode 100644 src/clj/automaton_core/adapters/bb_edn.clj delete mode 100644 src/clj/automaton_core/adapters/code_formatter.clj create mode 100644 src/clj/automaton_core/os/code_formatter.clj delete mode 100644 test/clj/automaton_core/adapters/bb_edn_test.clj delete mode 100644 test/clj/automaton_core/adapters/code_files_test.clj delete mode 100644 test/clj/automaton_core/adapters/code_formatter_test.clj create mode 100644 version.edn diff --git a/bb.edn b/bb.edn index d77cdbf2..1e10fefc 100644 --- a/bb.edn +++ b/bb.edn @@ -1,98 +1,72 @@ -{:paths ["src/clj"] - :deps {hephaistox/automaton-build-app {:git/url "git@github.com:hephaistox/automaton-build-app.git" - :sha "33c8941cb6df63006bafaaf1d5e7f0383b10468a"}} - - :tasks {:requires [[automaton-build-app.log :as build-log] - [automaton-build-app.os.commands :as build-cmds] - [babashka.fs :as fs]] - :init (do - (defn- cicd? [] - (System/getenv "CI")) - - (defn qualified-name [s] - (apply str - (interpose "/" - ((juxt namespace name) (symbol s))))) - - (defn- task-name [] - (-> (babashka.tasks/current-task) - :name)) - - (defn run-bb - "Run the `body-fn` on the current bb environment" - [body-fn] - (build-log/trace-format "Run %s task on bb" (task-name)) - (let [ns (-> (symbol body-fn) - namespace - symbol)] - (require ns) - ((resolve body-fn) {:command-line-args *command-line-args*}))) - - (defn run-clj - [body-fn] - (build-log/trace-format "Run %s task on clj" (task-name)) - (build-cmds/execute-and-trace ["clojure" "-X:build" (qualified-name body-fn) - :command-line-args *command-line-args*])) - - (defn dispatch - "Execute the body-fn directy in currently running bb env - * `body` body to execute - * `executing-pf` could be :bb or :clj, the task will be executed on one or the other" - [body-fn executing-pf] - (if (= :clj executing-pf) - (run-clj body-fn) - (run-bb body-fn))) - - (defn execute-task - "Run the function and manage - Params: - * `body` body to execute - * `executing-pf` (Optional, default = :bb) could be :bb or :clj, the task will be executed on one or the other" - [body-fn & executing-pf] - (try - (build-log/info-format "Run %s task" (-> (current-task) - :name)) - (dispatch body-fn - (first executing-pf)) - (catch Exception e - (println (format "Error during execution of `%s`, %s`" (:name (current-task)) (pr-str (ex-message e)))) - (if (cicd?) - (println e) - (let [file (fs/create-temp-file {:suffix ".edn"})] - (println (format "See details in `%s`" (.toString (.toAbsolutePath file)))) - (spit (fs/file file) (prn-str e)) - "")) - (System/exit 1))))) - - blog {:doc "Transforms md file to pdf based on edn file" - :task (execute-task 'automaton-build-app.tasks.doc/blog-task :clj)} - - clean {:doc "Clean cache files for compiles, and logs" - :task (execute-task 'automaton-build-app.tasks.clean/clean)} - - clean-hard {:doc "Clean all files which are not under version control (it doesn't remove untracked file or staged files if there are eligible to `git add .`)" - :task (execute-task 'automaton-build-app.tasks.clean/clean-hard)} - - code-doc {:doc "Create the documentation of the app" - :task (execute-task 'automaton-build-app.tasks.code-helpers-clj/code-doc :clj)} - - compile-to-jar {:doc "Compile that code to a jar" - :task (execute-task 'automaton-build-app.tasks.code-helpers/compile-to-jar :clj)} - - gha {:doc "Github action command - is launched automatically by github" - :task (execute-task 'automaton-build-app.tasks.test/gha :clj)} - - gha-lconnect {:doc "Connect to a local container running this code" - :task (execute-task 'automaton-build-app.tasks.test/gha)} - - lconnect {:doc "Local connect - repl" - :task (execute-task 'automaton-build-app.tasks.code-helpers/lconnect)} - - ltest {:doc "Local test" - :task (execute-task 'automaton-build.app.test/ltest)} - - push {:doc "Push this repo" - :task (execute-task 'automaton-build-app.tasks.publication/push-from-local :clj)} - - update-deps {:doc "Update the dependencies, cider-nrepl and refactor are to be updated manually" - :task (execute-task 'automaton-build-app.tasks.code-helpers-clj/update-deps :clj)}}} +{:deps {hephaistox/automaton-build-app + {:local/root "../../automaton/automaton_build_app"}}, + :paths [], + :tasks + {:enter (let [task-name (-> (babashka.tasks/current-task) + :name + str)] + (def execute-task + (partial build-task-helper/execute-task + task-name + (build-task-helper/enter-tasks task-name {})))), + :init (build-task-helper/init-tasks), + :requires [[automaton-build-app.tasks-helper :as build-task-helper]], + blog {:doc "Transforms md file to pdf based on edn file", + :task (execute-task 'automaton-build-app.tasks.doc-clj/blog-task + {:executing-pf :clj})}, + clean {:doc "Clean cache files for compiles, and logs", + :task (execute-task 'automaton-build-app.tasks.clean/clean)}, + clean-hard + {:doc + "Clean all files which are not under version control (it doesn't remove untracked file or staged files if there are eligible to `git add .`)", + :task (execute-task 'automaton-build-app.tasks.clean/clean-hard)}, + code-doc {:doc "Create the documentation of the app", + :task (execute-task 'automaton-build-app.tasks.doc-clj/code-doc + {:executing-pf :clj})}, + compile-to-jar + {:doc "Compile that code to a jar", + :task (execute-task + 'automaton-build-app.tasks.code-helpers-clj/compile-to-jar + {:executing-pf :clj})}, + container-clear + {:doc "Clear all local containers", + :task + (execute-task + 'automaton-build-app.tasks.container-publication/container-clean)}, + container-list + {:doc "List all available containers", + :task + (execute-task + 'automaton-build-app.tasks.container-publication/container-list)}, + gha {:doc "Github action command - is launched automatically by github", + :task (execute-task 'automaton-build-app.tasks.test-clj/gha + {:executing-pf :clj})}, + gha-lconnect {:doc "Connect to a local container running this code", + :task (execute-task + 'automaton-build-app.tasks.test/gha-lconnect)}, + la {:doc "Local acceptance test", + :task (execute-task 'automaton-build-app.tasks.test/la)}, + lconnect {:doc "Local connect - repl", + :task (execute-task + 'automaton-build-app.tasks.code-helpers/lconnect)}, + ltest {:doc "Local test", + :task (execute-task 'automaton-build-app.tasks.test/ltest)}, + publish + {:doc "Publish the container, useful to push the github container itself", + :task + (execute-task + 'automaton-build-app.tasks.container-publication/push-gha-from-local)}, + push {:doc "Push this repo", + :task (execute-task + 'automaton-build-app.tasks.publication-clj/push-from-local + {:executing-pf :clj})}, + report {:doc "Creates the reports of code analyzis", + :task (execute-task + 'automaton-build-app.tasks.code-analyze-clj/reports + {:executing-pf :clj})}, + update-deps + {:doc + "Update the dependencies, cider-nrepl and refactor are to be updated manually", + :task (execute-task + 'automaton-build-app.tasks.code-helpers-clj/update-deps + {:executing-pf :clj})}}} \ No newline at end of file diff --git a/build_config.edn b/build_config.edn index 1ad74ffc..427a57d2 100644 --- a/build_config.edn +++ b/build_config.edn @@ -3,19 +3,29 @@ :branch "main"} :as-lib hephaistox/automaton-core :major-version "1.2.%s" + :gha-container {:repo-url "git@github.com:hephaistox/gha_image.git" + :repo-branch "main" + :account "hephaistox" + :workflows [[".github/workflows/commit_validation.yml" "gha-automaton-core"]]} + :shadow-cljs {:target-build nil} :jar {:class-dir "target/classes" :excluded-aliases #{} :target-filename "target/%s-%s.jar"}} :lconnect {:aliases [:common-test :env-development-repl]} :ltest {:aliases [:env-development-test :common-test]} + :la {:selected-tasks ["blog" "clean" "clean-hard" "code-doc" "compile-to-jar" "container-clear" "container-list" "gha" "gha-lconnect" "ltest" "publish-gha-container" "push" "report" "update-deps"]} :customer-materials {:html-dir "tmp/html" :dir "customer_materials" :pdf-dir "tmp/pdf"} - :container-repo {:account "hephaistox"} :doc {:dir "docs" :archi {:dir "docs/archi/"} :code-stats {:output-file "docs/code/stats.md"} - :reports {:output-files {:automaton-build-app.code-helpers.test-toolings/comments "XX"}} + :reports {:output-files {:comments "docs/code/comments.edn" + :alias "docs/code/alias.edn" + :css "docs/code/css.edn" + :deps-ns "docs/code/deps-ns.svg" + :deps "docs/code/deps.png" + :ns "docs/code/ns.png"}} :code-doc {:dir "docs/code" :title "Build app automaton" :description "Autonomous project to build an hephaistox app"}} diff --git a/deps.edn b/deps.edn index 50255400..d9a9e6cd 100644 --- a/deps.edn +++ b/deps.edn @@ -1,41 +1,4 @@ -{:aliases - {:common-test {:exec-fn cognitect.test-runner.api/test - :extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner", - :sha "7284cda41fb9edc0f3bc6b6185cfb7138fc8a023"}, - org.clojure/tools.namespace #:mvn{:version "1.4.4"}, - org.clojure/tools.reader #:mvn{:version "1.3.6"}}} - - :env-development-repl {:extra-paths ["env/development/resources" - "env/development/src/clj" - "env/development/src/cljc"] - :extra-deps {cider/cider-nrepl {:mvn/version "0.21.1"} - org.clojure/core.async {:mvn/version "1.6.681"}} - :main-opts ["-m" "automaton-core.repl-core"] - :jvm-opts ["-Dheph-conf=env/development/config.edn" - "-Dheph-common-conf=env/common_config.edn"]}, - - :env-development-test {:jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/log4j2-factory" - ;;TODO I don't get where I'm wrong, shouldn't it suppose to disable logs like that, it's like the files are found, but the log is still printed - "-Dlog4j.configurationFile=resources/log_config/appenders.properties,resources/log_config/logging-tests.properties" - "-Dheph-conf=env/development/config.edn" - "-Dheph-common-conf=env/common_config.edn"], - :extra-paths ["test/clj" - "test/cljc" - "test/resources"] - :main-opts ["-m" "cognitect.test-runner" - "-r" ".*-test.*" - "-d" "test/clj" - "-d" "test/cljc"]} - - :build {:extra-deps {hephaistox/automaton-build-app {:git/url "git@github.com:hephaistox/automaton-build-app.git" - :sha "33c8941cb6df63006bafaaf1d5e7f0383b10468a"}}} - - :cljs-deps {:extra-paths ["src/cljs" "src/cljc" "resources" "test/cljs" "test/cljc"] - :extra-deps {thheller/shadow-cljs {:mvn/version "2.25.8"} - cider/cider-nrepl {:mvn/version "0.21.1"} - binaryage/devtools {:mvn/version "1.0.7"}}}} - - :deps {babashka/fs #:mvn{:version "0.4.19"}, +{:deps {babashka/fs #:mvn{:version "0.4.19"}, babashka/process #:mvn{:version "0.5.21"}, danlentz/clj-uuid #:mvn{:version "0.1.9"}, metosin/malli #:mvn{:version "0.13.0"}, @@ -53,7 +16,44 @@ refactor-nrepl/refactor-nrepl #:mvn{:version "3.9.0"}, org.clojure/clojure #:mvn{:version "1.11.1"}, org.clojure/tools.logging #:mvn{:version "1.2.4"} - zprint/zprint {:mvn/version "1.2.8"} org.clojure/tools.cli #:mvn{:version "1.0.219"}} - :paths ["src/clj" "src/cljc" "resources"]} + :paths ["src/clj" "src/cljc" "resources"] + + :aliases {:common-test {:exec-fn cognitect.test-runner.api/test + :extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner", + :sha "7284cda41fb9edc0f3bc6b6185cfb7138fc8a023"}, + org.clojure/tools.namespace #:mvn{:version "1.4.4"}, + org.clojure/tools.reader #:mvn{:version "1.3.6"}} + :extra-paths ["test/clj" "test/cljc" "test/resources"] + :jvm-opts ["-Dheph-conf=env/test/config.edn" + "-Dheph-common-conf=env/common_config.edn"]} + + :build {:extra-deps {hephaistox/automaton-build-app {:git/url "git@github.com:hephaistox/automaton-build-app.git" + :sha "33c8941cb6df63006bafaaf1d5e7f0383b10468a"}}} + + :env-development-repl {:extra-paths ["env/development/resources" + "env/development/src/clj" + "env/development/src/cljc"] + :extra-deps {cider/cider-nrepl {:mvn/version "0.21.1"} + org.clojure/core.async {:mvn/version "1.6.681"}} + :main-opts ["-m" "automaton-core.repl-core"] + :jvm-opts ["-Dheph-conf=env/development/config.edn" + "-Dheph-common-conf=env/common_config.edn"]}, + + :env-development-test {:jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/log4j2-factory" + "-Dhephaistox-in-test=true" + "-Dlog4j.configurationFile=resources/log_config/appenders.properties,resources/log_config/logging-tests.properties"] + :main-opts ["-m" "cognitect.test-runner" + "-r" ".*-test.*" + "-d" "test/clj" + "-d" "test/cljc"]} + + :cljs-deps {:extra-paths ["src/cljs" "src/cljc" "resources" "test/cljs" "test/cljc"] + :extra-deps {thheller/shadow-cljs {:mvn/version "2.25.8"} + cider/cider-nrepl {:mvn/version "0.21.1"} + binaryage/devtools {:mvn/version "1.0.7"}}} + + :bb-deps {:extra-deps {hephaistox/automaton-build-app {:local/root "../../automaton/automaton_build_app"} + #_{:git/url "git@github.com:hephaistox/automaton-build-app.git" + :sha "df88ec49ea3cdbc8606c22cc1635ac7a309d8c03"}}}}} diff --git a/docs/code/alias.edn b/docs/code/alias.edn new file mode 100644 index 00000000..5dc06bae --- /dev/null +++ b/docs/code/alias.edn @@ -0,0 +1,2 @@ +;; List of aliases referencing many namespaces Tue Oct 24 19:33:10 CEST 2023 +{} \ No newline at end of file diff --git a/docs/code/comments.edn b/docs/code/comments.edn new file mode 100644 index 00000000..22f50f3e --- /dev/null +++ b/docs/code/comments.edn @@ -0,0 +1 @@ +List of forbidden comments \ No newline at end of file diff --git a/docs/code/css.edn b/docs/code/css.edn new file mode 100644 index 00000000..ec5d538d --- /dev/null +++ b/docs/code/css.edn @@ -0,0 +1 @@ +List of forbidden css forms \ No newline at end of file diff --git a/docs/code/deps-ns.svg b/docs/code/deps-ns.svg new file mode 100644 index 00000000..99f83c53 --- /dev/null +++ b/docs/code/deps-ns.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b973c85e7b8939e5ab17a6be19047f5ec90bd4f2589a132abdb58d6e5d8c4a95 +size 29568 diff --git a/docs/code/deps.png b/docs/code/deps.png new file mode 100644 index 00000000..fe2528da --- /dev/null +++ b/docs/code/deps.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf94152c0c813e1cc7810ffb2b13b1a77ee2670e380fb82ce4b09f0bee8bc344 +size 230515 diff --git a/docs/code/namespace.edn b/docs/code/namespace.edn new file mode 100644 index 00000000..2e4990c9 --- /dev/null +++ b/docs/code/namespace.edn @@ -0,0 +1,2 @@ +;; List of aliases referencing many namespaces Tue Oct 24 19:33:11 CEST 2023 +{} \ No newline at end of file diff --git a/env/development/resources/version.edn b/env/development/resources/version.edn new file mode 100644 index 00000000..38f8f339 --- /dev/null +++ b/env/development/resources/version.edn @@ -0,0 +1,3 @@ +;; Last generated version, note a failed push consume a number Tue Oct 24 +;; 19:32:54 CEST 2023 +{:major-version "1.2.%s", :minor-version 3, :version "1.2.3"} \ No newline at end of file diff --git a/env/development/src/clj/automaton_core/repl_core.clj b/env/development/src/clj/automaton_core/repl_core.clj index d76b1c7f..96b9e84e 100644 --- a/env/development/src/clj/automaton_core/repl_core.clj +++ b/env/development/src/clj/automaton_core/repl_core.clj @@ -1,12 +1,11 @@ (ns automaton-core.repl-core "repl for `automaton-core` stand alone This namespace is called to start a repl on `automaton-core` only" - (:require - [automaton-core.log :as log] - [automaton-core.repl :as core-repl] - [clojure.core.async :refer [> (files/search-files config-path - (str "{"build-config-filename",*/" build-config-filename ",*/*/" build-config-filename "}")) + (str "{" + build-config-filename + ",*/" + build-config-filename + ",*/*/" + build-config-filename + "}")) flatten (filter (comp not nil?)))) ([] (search-for-build-config ""))) @@ -40,17 +40,13 @@ (defn build-configs-libs [accepted-libs] (let [build-configs (search-for-build-config) - libs (keep - (fn [build-filename] - (let [edn-file (edn-utils/read-edn build-filename)] - (when-let [lib (get-in - edn-file - [:publication :as-lib])] - (when (some #{lib} accepted-libs) - {:lib lib - :dir (get-in edn-file [:monorepo - :app-dir])})))) - build-configs)] + libs (keep (fn [build-filename] + (let [edn-file (edn-utils/read-edn build-filename)] + (when-let [lib (get-in edn-file [:publication :as-lib])] + (when (some #{lib} accepted-libs) + {:lib lib, + :dir (get-in edn-file [:monorepo :app-dir])})))) + build-configs)] libs)) (defn spit-build-config @@ -60,11 +56,7 @@ * `content` to spit * `msg` (optional) to add on the top of the file" ([app-dir content msg] - (let [filename (files/create-file-path app-dir - build-config-filename)] - (edn-utils/spit-edn filename - content - msg) + (let [filename (files/create-file-path app-dir build-config-filename)] + (edn-utils/spit-edn filename content msg) filename)) - ([app-dir content] - (spit-build-config app-dir content nil))) + ([app-dir content] (spit-build-config app-dir content nil))) diff --git a/src/clj/automaton_core/adapters/code_formatter.clj b/src/clj/automaton_core/adapters/code_formatter.clj deleted file mode 100644 index 91fc7a1b..00000000 --- a/src/clj/automaton_core/adapters/code_formatter.clj +++ /dev/null @@ -1,29 +0,0 @@ -(ns automaton-core.adapters.code-formatter - "Format code - Proxy to [zprint](https://github.com/kkinnear/zprint)" - (:require - [automaton-core.adapters.files :as files] - [automaton-core.adapters.time :as time] - [clojure.string :as str] - [zprint.core :as zp])) - -(defn format-content - "Format the data structure" - [content] - (zp/zprint-str content)) - - -(defn format-file - "Format the `clj` or `edn` file - Params: - * `filename` to format - * `header` (optional) is written at the top of the file" - ([filename header] - (let [format-content (zp/zprint-file-str (slurp filename) - nil)] - (files/spit-file filename - (apply str [(when-not (str/blank? header) - (println-str ";;" header (time/now-str))) - format-content])))) - ([filename] - (format-file filename nil))) diff --git a/src/clj/automaton_core/adapters/commands.clj b/src/clj/automaton_core/adapters/commands.clj index bccd46db..b35e32e7 100644 --- a/src/clj/automaton_core/adapters/commands.clj +++ b/src/clj/automaton_core/adapters/commands.clj @@ -1,33 +1,23 @@ (ns automaton-core.adapters.commands "Library to execute a set of commands" - (:require - [clojure.java.io :as io] - [clojure.string :as str] - - [babashka.process :as p] - - [automaton-core.adapters.files :as files] - [automaton-core.log :as log] - [automaton-core.adapters.schema :as schema] - [automaton-core.adapters.string :as string] - [automaton-core.adapters.edn-utils :as edn-utils])) + (:require [automaton-core.adapters.files :as files] + [automaton-core.adapters.schema :as schema] + [automaton-core.log :as log] + [babashka.process :as process] + [clojure.java.io :as io] + [clojure.string :as str])) (def size-command "Size of the command line to be managed, measured on mcbook pro" 185) (def commands-schema - [:vector [:or - [:tuple - [:vector [:string]] - :map] - [:tuple - [:vector [:string]]]]]) + [:vector + [:or [:tuple [:vector [:string]] :map] [:tuple [:vector [:string]]]]]) (def glob-command-params "Command params globals" - {:in :inherit - :blocking? true}) + {:in :inherit, :blocking? true}) (defn stream-execute-command* "Command processing function, that's redirecting output to a log fn as a stream, to allow information to be viewed during operation. @@ -35,38 +25,31 @@ It's additionally focused on both stderr and stdout as in some situations (like docker build that is outputing to stderr) you read from stdout it will block, but when you also want to read from stderr, you'll have to do the first in a future or so, to not block that. https://clojurians.slack.com/archives/CLX41ASCS/p1694600409401029" [command dir] - (let [proc (p/process command - {:dir dir - :shutdown p/destroy-tree})] + (let [proc (process/process command + {:dir dir, :shutdown process/destroy-tree})] (future (with-open [rdr (io/reader (:out proc))] (binding [*in* rdr] (loop [] - (when-let [line (read-line)] - (log/trace line)) - (when (or (.ready rdr) (.isAlive (:proc proc))) - (recur)))))) + (when-let [line (read-line)] (log/trace line)) + (when (or (.ready rdr) (.isAlive (:proc proc))) (recur)))))) (with-open [rdr (io/reader (:err proc))] (binding [*in* rdr] (loop [] - (when-let [line (read-line)] - (log/trace line)) - (when (or (.ready rdr) (.isAlive (:proc proc))) - (recur))))))) + (when-let [line (read-line)] (log/trace line)) + (when (or (.ready rdr) (.isAlive (:proc proc))) (recur))))))) (defn execute-command* "execute-command core function that's used to process the command." [command dir out file in blocking?] - (let [proc (p/process command - {:dir dir - :shutdown p/destroy-tree - :out out - :out-file file - :err out - :err-file file - :in in})] - (if blocking? - (p/check proc) - proc))) + (let [proc (process/process command + {:dir dir, + :shutdown process/destroy-tree, + :out out, + :out-file file, + :err out, + :err-file file, + :in in})] + (if blocking? (process/check proc) proc))) (defn execute-command "Execute a command, described with @@ -75,58 +58,43 @@ * `cmd-params` list of parameters for that particular command * `cmds-params` list of parmeters set once for the global command" [[command cmd-params] cmds-params] - (let [merged-params (merge glob-command-params - cmd-params - cmds-params) - execute-command-params {:command command - :merged-params merged-params - :cmd-params cmd-params + (let [merged-params (merge glob-command-params cmd-params cmds-params) + execute-command-params {:command command, + :merged-params merged-params, + :cmd-params cmd-params, :cmds-params cmds-params} {:keys [dir out in blocking? stream?]} merged-params filename out str-command (str/join " " command) - file (if (or (nil? out) - (= out :string)) - nil - (io/file filename)) + file (if (or (nil? out) (= out :string)) nil (io/file filename)) out (cond (= out :string) :string out :write :else :inherit) - blocking? (or (= out :string) - blocking?)] - + blocking? (or (= out :string) blocking?)] (files/create-dirs dir) - (log/debug (string/limit-length str-command - size-command - "`" - (str "` in directory : `" (files/absolutize dir)) - (fn [msg] - (log/trace (edn-utils/spit-in-tmp-file msg))))) - (when (and (not= out :string) - filename) + (log/debug-format "%s - in directory `%s`" + str-command + (files/absolutize dir)) + (when (and (not= out :string) filename) (log/info " -> output = " filename)) - - (try - (if stream? - (stream-execute-command* command dir) - (execute-command* command dir out file in blocking?)) - (catch java.io.IOException e - (throw (ex-info (str "Directory does not exist") - (merge {:exception e} - execute-command-params)))) - (catch clojure.lang.ExceptionInfo e - (let [{:keys [exit type]} (ex-data e)] - (if (= type :babashka.process/error) - (throw (ex-info (str "Command `" str-command "` failed on exit code " exit) - (merge execute-command-params - {:exception e}))) - (throw (ex-info (str "Command `" str-command "` failed ") - (merge execute-command-params - {:exception e})))))) - (catch Exception e - (throw (ex-info (str "Command `" str-command "` failed ") - (merge execute-command-params - {:exception e}))))))) + (try (if stream? + (stream-execute-command* command dir) + (execute-command* command dir out file in blocking?)) + (catch java.io.IOException e + (throw (ex-info (str "Directory does not exist") + (merge {:exception e} execute-command-params)))) + (catch clojure.lang.ExceptionInfo e + (let [{:keys [exit type]} (ex-data e)] + (if (= type :babashka.process/error) + (throw (ex-info (str "Command `" str-command + "` failed on exit code " exit) + (merge execute-command-params {:exception e}))) + (throw (ex-info (str "Command `" str-command "` failed ") + (merge execute-command-params + {:exception e})))))) + (catch Exception e + (throw (ex-info (str "Command `" str-command "` failed ") + (merge execute-command-params {:exception e}))))))) (defn exec-cmds "Execute commands with their default parameters @@ -135,14 +103,9 @@ * the second is the set of parameters, which allow to be specific for each command Params: * `commands` tokenize command" - ([commands] - (exec-cmds commands {})) + ([commands] (exec-cmds commands {})) ([commands default-params] - (schema/schema-valid-or-throw commands-schema - commands - "Malformed command") + (schema/schema-valid-or-throw commands-schema commands "Malformed command") (apply str - (doall - (for [command commands] - (:out - (execute-command command default-params))))))) + (doall (for [command commands] + (:out (execute-command command default-params))))))) diff --git a/src/clj/automaton_core/adapters/deps_edn.clj b/src/clj/automaton_core/adapters/deps_edn.clj index dbba124a..58f9cf4f 100644 --- a/src/clj/automaton_core/adapters/deps_edn.clj +++ b/src/clj/automaton_core/adapters/deps_edn.clj @@ -1,20 +1,17 @@ (ns automaton-core.adapters.deps-edn "Proxy to read of deps.edn file" - (:require - [automaton-core.adapters.edn-utils :as edn-utils] - [automaton-core.adapters.files :as files] - [automaton-core.log :as log])) + (:require [automaton-core.adapters.edn-utils :as edn-utils] + [automaton-core.adapters.files :as files] + [automaton-core.log :as log])) -(def deps-edn - "deps.edn") +(def deps-edn "deps.edn") (defn get-deps-filename "Get the deps-file of the application Params: * `app-dir` is where the application is stored" [app-dir] - (files/create-file-path app-dir - deps-edn)) + (files/create-file-path app-dir deps-edn)) (defn load-deps "Load the current project `deps.edn` files" @@ -37,19 +34,12 @@ * `deps-edn` is the content of the file" [as-lib commit-id deps-edn] (if-let [old-commit-id (get-in deps-edn [:deps as-lib :git/sha])] - (if (= commit-id - old-commit-id) - (do - (log/trace "Skip update as it already uptodate") - deps-edn) + (if (= commit-id old-commit-id) + (do (log/trace "Skip update as it already uptodate") deps-edn) (do (log/trace "Change commit from `" old-commit-id "` to `" commit-id "`") - (assoc-in deps-edn - [:deps as-lib :git/sha] - commit-id))) - (do - (log/trace "Skip as it does not use lib `%s:%s`") - deps-edn))) + (assoc-in deps-edn [:deps as-lib :git/sha] commit-id))) + (do (log/trace "Skip as it does not use lib `%s:%s`") deps-edn))) (defn extract-paths "Extracts the `:paths` and `:extra-paths` from a given `deps.edn` @@ -57,45 +47,38 @@ Params: * `deps-edn` content the deps edn file to search extract path in * `excluded-aliases` is a collection of aliases to exclude" - ([{:keys [paths aliases] - :as _deps-edn} excluded-aliases] - (let [selected-aliases (apply dissoc aliases - excluded-aliases) + ([{:keys [paths aliases], :as _deps-edn} excluded-aliases] + (let [selected-aliases (apply dissoc aliases excluded-aliases) alias-paths (mapcat (fn [[_alias-name paths]] (apply concat - (vals (select-keys paths [:extra-paths :paths])))) - selected-aliases)] + (vals (select-keys paths + [:extra-paths :paths])))) + selected-aliases)] (->> alias-paths (concat paths) sort dedupe (into [])))) - ([deps-edn] - (extract-paths deps-edn #{}))) + ([deps-edn] (extract-paths deps-edn #{}))) (defn extract-deps "Extract dependencies in a `deps.edn` file Params: * `deps-edn` is the content of the file to search dependencies in * `excluded-aliases` is a collection of aliases to exclude" - [{:keys [deps aliases] :as _deps-edn} excluded-aliases] + [{:keys [deps aliases], :as _deps-edn} excluded-aliases] (let [selected-aliases (apply dissoc aliases excluded-aliases)] (->> selected-aliases (map (fn [[_ alias-defs]] - (vals - (select-keys alias-defs [:extra-deps :deps])))) + (vals (select-keys alias-defs [:extra-deps :deps])))) (apply concat) (into {}) (concat deps) - (map (fn [[deps-name deps-map]] - [deps-name deps-map]))))) + (map (fn [[deps-name deps-map]] [deps-name deps-map]))))) (defn remove-deps "Remove the dependency called `dep-lib-to-remove` in the `deps` * `deps-edn` the deps edn content to update * `dep-libs-to-remove` is the list of dependencies to remove" [deps-edn dep-libs-to-remove] - (update deps-edn - :deps - #(apply dissoc % - dep-libs-to-remove))) + (update deps-edn :deps #(apply dissoc % dep-libs-to-remove))) diff --git a/src/clj/automaton_core/adapters/edn_utils.clj b/src/clj/automaton_core/adapters/edn_utils.clj index 822882f3..136ea92c 100644 --- a/src/clj/automaton_core/adapters/edn_utils.clj +++ b/src/clj/automaton_core/adapters/edn_utils.clj @@ -1,20 +1,16 @@ (ns automaton-core.adapters.edn-utils "Edn file manipulation" - (:require - [automaton-core.adapters.code-formatter :as code-formatter] - [automaton-core.adapters.files :as files] - [automaton-core.configuration :as conf] - [automaton-core.log :as log] - [automaton-core.utils.uuid-gen :as uuid] - [clojure.edn :as edn])) + (:require [automaton-core.os.code-formatter :as code-formatter] + [automaton-core.adapters.files :as files] + [automaton-core.configuration :as conf] + [automaton-core.log :as log] + [automaton-core.utils.uuid-gen :as uuid] + [clojure.edn :as edn])) (defn is-clojure-like-file "Returns true if the file's extension is clojure like" [filename] - (boolean - (re-find #"\.clj[sc]?$" - (or filename - "")))) + (boolean (re-find #"\.clj[sc]?$" (or filename "")))) (defn read-edn "Read the `.edn` file, @@ -30,20 +26,17 @@ ([edn-filename loader-fn] (let [edn-filename (files/absolutize edn-filename) _ (log/trace "Load file:" edn-filename) - edn-content (try - (loader-fn edn-filename) - (catch Exception e - (throw (ex-info (format "Unable to load the file `%s`" edn-filename) - {:caused-by e - :file-name edn-filename}))))] - (try - (edn/read-string edn-content) - (catch Exception e - (throw (ex-info (format "File `%s` is not an edn" edn-filename) - {:caused-by e - :file-name edn-filename})))))) - ([edn-filename] - (read-edn edn-filename files/read-file))) + edn-content + (try (loader-fn edn-filename) + (catch Exception e + (throw (ex-info (format "Unable to load the file `%s`" + edn-filename) + {:caused-by e, :file-name edn-filename}))))] + (try (edn/read-string edn-content) + (catch Exception e + (throw (ex-info (format "File `%s` is not an edn" edn-filename) + {:caused-by e, :file-name edn-filename})))))) + ([edn-filename] (read-edn edn-filename files/read-file))) (defn read-edn-or-nil "Read the `.edn` file, @@ -51,12 +44,8 @@ * `file` could be a string representing the name of the file to load or a (io/resource) object representing the name of the file to load" ([edn-file-name loader-fn] - (try - (read-edn edn-file-name loader-fn) - (catch Exception _ - nil))) - ([edn-file-name] - (read-edn-or-nil edn-file-name slurp))) + (try (read-edn edn-file-name loader-fn) (catch Exception _ nil))) + ([edn-file-name] (read-edn-or-nil edn-file-name slurp))) (defn spit-edn "Spit the `content` in the edn file called `deps-edn-filename`. @@ -67,20 +56,16 @@ * `header` the header that is added to the content, followed by the timestamp - is automatically preceded with ;; Return the content of the file" ([edn-filename content header] - (try - (log/trace "Spit edn file:" edn-filename) - (files/spit-file edn-filename - content) - (code-formatter/format-file edn-filename - header) - content - (catch Exception e - (throw (ex-info "Impossible to update the .edn file" - {:deps-edn-filename edn-filename - :exception e - :content content}))))) - ([deps-edn-filename content] - (spit-edn deps-edn-filename content nil))) + (try (log/trace "Spit edn file:" edn-filename) + (files/spit-file edn-filename content) + (code-formatter/format-file edn-filename header) + content + (catch Exception e + (throw (ex-info "Impossible to update the .edn file" + {:deps-edn-filename edn-filename, + :exception e, + :content content}))))) + ([deps-edn-filename content] (spit-edn deps-edn-filename content nil))) (defn update-edn-content "Update the edn file content with the `params-to-merge` map @@ -93,11 +78,8 @@ " ([edn-filename update-fn header] (let [bb-config (read-edn edn-filename)] - (spit-edn edn-filename - (update-fn bb-config) - header))) - ([edn-filename update-fn] - (update-edn-content edn-filename update-fn nil))) + (spit-edn edn-filename (update-fn bb-config) header))) + ([edn-filename update-fn] (update-edn-content edn-filename update-fn nil))) (defn spit-edn-or-file "Spit the file as an edn if it is a clojure file, or spit it with no modification otherwise" @@ -121,13 +103,9 @@ * `data` the data to spit * `formatting?` (Optional, default = true) is the content formatted" ([data formatting?] - (let [filename (create-tmp-edn) - ;; Important to print exception properly - formatted-data (if formatting? - (code-formatter/format-content data) - data)] - (files/spit-file filename formatted-data) - (format " See file `%s` for details" - (files/absolutize filename)))) - ([data] - (spit-in-tmp-file data true))) + (let [filename (create-tmp-edn)] + (files/spit-file filename data) + ;; Important to print exception properly + (when formatting? (code-formatter/format-file filename)) + (format " See file `%s` for details" (files/absolutize filename)))) + ([data] (spit-in-tmp-file data true))) diff --git a/src/clj/automaton_core/adapters/env_variables.clj b/src/clj/automaton_core/adapters/env_variables.clj index 0665ce94..24aadf14 100644 --- a/src/clj/automaton_core/adapters/env_variables.clj +++ b/src/clj/automaton_core/adapters/env_variables.clj @@ -1,8 +1,7 @@ -(ns automaton-core.adapters.env-variables - "Operating enviroment variables") +(ns automaton-core.adapters.env-variables "Operating enviroment variables") (defn get-env - "Get the environment variable + "Get the environment variable Params: * `var-name` name of the environment variable to be retrieved" [var-name] @@ -11,5 +10,4 @@ (defn get-envs "A map of all available environment variables" [] - (into {} - (System/getenv))) + (into {} (System/getenv))) diff --git a/src/clj/automaton_core/adapters/files.clj b/src/clj/automaton_core/adapters/files.clj index 8a729a66..0b8abc1c 100644 --- a/src/clj/automaton_core/adapters/files.clj +++ b/src/clj/automaton_core/adapters/files.clj @@ -1,12 +1,11 @@ (ns automaton-core.adapters.files "Tools to manipulate local files Is a proxy to babashka.fs tools" - (:require - [automaton-core.configuration :as conf] - [automaton-core.log :as log] - [automaton-core.utils.uuid-gen :as uuid] - [babashka.fs :as fs] - [clojure.string :as str])) + (:require [automaton-core.configuration :as conf] + [automaton-core.log :as log] + [automaton-core.utils.uuid-gen :as uuid] + [babashka.fs :as fs] + [clojure.string :as str])) (def file-separator "Symbol to separate directories. @@ -16,13 +15,9 @@ (defn absolutize "Transform a file or dir name in an absolute path" [relative-path] - (when relative-path - (str (fs/absolutize relative-path)))) + (when relative-path (str (fs/absolutize relative-path)))) -(defn hidden? - "Return true if the path is hidden" - [path] - (fs/hidden? path)) +(defn hidden? "Return true if the path is hidden" [path] (fs/hidden? path)) (defn delete-files "Deletes the files which are given in the list. @@ -30,23 +25,20 @@ [file-list] (doseq [file file-list] (if (fs/directory? file) - (do - (log/debug "Directory " (absolutize file) " is deleted") - (fs/delete-tree file)) - (do - (log/debug "File " (absolutize file) " is deleted") - (fs/delete-if-exists file))))) + (do (log/debug "Directory " (absolutize file) " is deleted") + (fs/delete-tree file)) + (do (log/debug "File " (absolutize file) " is deleted") + (fs/delete-if-exists file))))) (defn- copy-files-or-dir-validate "Internal function to validate data aof copy files or dir" [files] (when-not (and (sequential? files) - (every? #(or (string? %) - (= java.net.URL - (class %))) - files)) - (throw (ex-info "The `files` parameter should be a sequence of string or `java.net.URL`" - {:files files})))) + (every? #(or (string? %) (= java.net.URL (class %))) files)) + (throw + (ex-info + "The `files` parameter should be a sequence of string or `java.net.URL`" + {:files files})))) (defn copy-files-or-dir "Copy the files, even if they are directories to the target @@ -55,63 +47,58 @@ [files target-dir] (log/debug "Copy files from `" files "` to `" target-dir "`") (copy-files-or-dir-validate files) - (try - (fs/create-dirs target-dir) - (doseq [file files] - (log/debug "Copy from " file " to " target-dir) - (if (fs/directory? file) - (do - (log/trace (format "Copy `%s` to `%s`" - (absolutize file) - (absolutize target-dir))) - (fs/copy-tree file target-dir - {:replace-existing true - :copy-attributes true})) - (do - (log/trace (format "Copy `%s` to `%s`" - (absolutize file) - (absolutize target-dir))) - (fs/copy file target-dir - {:replace-existing true - :copy-attributes true})))) - (catch Exception e - (throw (ex-info "Unexpected exception during copy" - {:exception e - :files files - :target-dir target-dir}))))) + (try (fs/create-dirs target-dir) + (doseq [file files] + (log/debug "Copy from " file " to " target-dir) + (if (fs/directory? file) + (do (log/trace (format "Copy `%s` to `%s`" + (absolutize file) + (absolutize target-dir))) + (fs/copy-tree file + target-dir + {:replace-existing true, :copy-attributes true})) + (do (log/trace (format "Copy `%s` to `%s`" + (absolutize file) + (absolutize target-dir))) + (fs/copy file + target-dir + {:replace-existing true, :copy-attributes true})))) + (catch Exception e + (throw (ex-info + "Unexpected exception during copy" + {:exception e, :files files, :target-dir target-dir}))))) (defn directory-exists? "Check directory existance" [directory-path] - (and (fs/exists? directory-path) - (fs/directory? directory-path))) + (and (fs/exists? directory-path) (fs/directory? directory-path))) (defn is-existing-file? "Check if this the path exist and is not a directory" [path] - (and (fs/exists? path) - (not (fs/directory? path)))) + (and (fs/exists? path) (not (fs/directory? path)))) (defn is-existing-dir? "Check if this the path exist and is a directory" [path] - (and (fs/exists? path) - (fs/directory? path))) + (and (fs/exists? path) (fs/directory? path))) (defn create-dirs "Create a directory" [dir] (when (is-existing-file? dir) - (throw (ex-info (format "Can't create a directory `%s` as a file already exists with that name" - (absolutize dir)) - {:dir dir}))) + (throw + (ex-info + (format + "Can't create a directory `%s` as a file already exists with that name" + (absolutize dir)) + {:dir dir}))) (when-not (fs/exists? dir) - (try - (fs/create-dirs dir) - (catch Exception e - (throw (ex-info (format "The parameter is not a valid directory: `%s`" dir) - {:dir (absolutize dir) - :exception e}))))) + (try (fs/create-dirs dir) + (catch Exception e + (throw (ex-info + (format "The parameter is not a valid directory: `%s`" dir) + {:dir (absolutize dir), :exception e}))))) true) (defn remove-trailing-separator @@ -149,17 +136,15 @@ * `(files/search-files \"\" \"**{.clj,.cljs,.cljc,.edn}\")` search all clj files in pwd directory" ([root pattern options] (when-not (directory-exists? root) - (throw (ex-info (str root " is expected to be a directory") {:root root - :pattern pattern - :options options}))) + (throw (ex-info (str root " is expected to be a directory") + {:root root, :pattern pattern, :options options}))) (into [] (map str - (fs/glob root pattern (merge {:hidden true - :recursive true - :follow-links true} - options))))) - ([root pattern] - (search-files root pattern {}))) + (fs/glob root + pattern + (merge {:hidden true, :recursive true, :follow-links true} + options))))) + ([root pattern] (search-files root pattern {}))) (defn list-subdir "List subdirectories" @@ -175,14 +160,12 @@ (defn for-each "Apply fn-each on each files in a directory" [dir fn-each] - (doseq [file (fs/list-dir dir)] - (fn-each (str file)))) + (doseq [file (fs/list-dir dir)] (fn-each (str file)))) (defn change-extension "Change the extension" [file-name new-extension] - (str (fs/strip-ext file-name) - new-extension)) + (str (fs/strip-ext file-name) new-extension)) (defn modified-since "Return true if anchor is older than one of the file in file-set" @@ -194,9 +177,9 @@ [source-file relative-name] (let [source-subdirs (fs/components source-file) subdirs (mapv str - (if (fs/directory? source-file) - source-subdirs - (butlast source-subdirs))) + (if (fs/directory? source-file) + source-subdirs + (butlast source-subdirs))) new-name (conj subdirs relative-name)] (apply create-file-path new-name))) @@ -207,64 +190,54 @@ (when-not (str/blank? filename) (if (fs/directory? filename) filename - (str - (when (= (str file-separator) - (str (first filename))) - file-separator) - (->> filename - fs/components - butlast - (map str) - (apply create-dir-path)))))) + (str (when (= (str file-separator) (str (first filename))) file-separator) + (->> filename + fs/components + butlast + (map str) + (apply create-dir-path)))))) (defn rename-file "Rename a file `src` to destination file `dst`" [src dst] - (try - (-> dst - extract-path - fs/create-dirs) - - (log/trace "Rename file " src " to " dst) - (fs/move src (fs/path dst)) - (catch Exception e - (throw (ex-info "Impossible to rename the file" - {:src (absolutize src) - :dst (absolutize dst) - :exception e}))))) + (try (-> dst + extract-path + fs/create-dirs) + (log/trace "Rename file " src " to " dst) + (fs/move src (fs/path dst)) + (catch Exception e + (throw (ex-info "Impossible to rename the file" + {:src (absolutize src), + :dst (absolutize dst), + :exception e}))))) (defn rename-dir "Rename a dir" [src dst] - (try - (log/trace "Rename directory " src " to " dst) - (fs/move src (fs/path dst)) - (catch Exception e - (throw (ex-info "Impossible to rename the directory" - {:src (absolutize src) - :dst (absolutize dst) - :exception e}))))) + (try (log/trace "Rename directory " src " to " dst) + (fs/move src (fs/path dst)) + (catch Exception e + (throw (ex-info "Impossible to rename the directory" + {:src (absolutize src), + :dst (absolutize dst), + :exception e}))))) (defn remove-file "Remove the file `filename`" [filename] - (try - (fs/delete-if-exists filename) - (catch Exception e - (throw (ex-info "Impossible to remove the file" - {:filename filename - :exception e}))))) + (try (fs/delete-if-exists filename) + (catch Exception e + (throw (ex-info "Impossible to remove the file" + {:filename filename, :exception e}))))) (defn read-file "Read the file `target-filename`" [target-filename] (log/trace (str "Reading file `" target-filename "`")) - (try - (slurp target-filename) - (catch Exception e - (throw (ex-info "Impossible to load the file" - {:target-filename target-filename - :exception e}))))) + (try (slurp target-filename) + (catch Exception e + (throw (ex-info "Impossible to load the file" + {:target-filename target-filename, :exception e}))))) (defn file-ized "Transform a name, like a namespace name or application name, in a directory compatible names" @@ -283,23 +256,21 @@ Will stop at the first modification Return modification? telling if at least one renaming has been done" [target-dir file-filter pattern pattern-replacement] - (loop [files (search-files target-dir - file-filter) + (loop [files (search-files target-dir file-filter) modification? false] (if (empty? files) modification? (let [filename (str (first files)) - new-filename (str/replace filename - pattern - pattern-replacement)] + new-filename (str/replace filename pattern pattern-replacement)] (if (= new-filename filename) (recur (rest files) modification?) - (cond - (is-existing-file? filename) (do (rename-file filename new-filename) - (recur (rest files) true)) - (is-existing-dir? filename) (do (rename-dir filename new-filename) - (recur (rest files) true)) - :else (recur (rest files) modification?))))))) + (cond (is-existing-file? filename) (do (rename-file filename + new-filename) + (recur (rest files) true)) + (is-existing-dir? filename) (do (rename-dir filename + new-filename) + (recur (rest files) true)) + :else (recur (rest files) modification?))))))) (defn rename-recursively "Search recursively all sub-dirs to be renamed from `template-app` in the `target-dir` directory @@ -308,12 +279,22 @@ * `pattern` is to find content in the namespace, for instance, as seen in [java pattern](https://docs.oracle.com/javase/10/docs/api/java/util/regex/Pattern.html), e.g. #\"foo(.*)bar\" * `pattern-replacement` is what to replace, according to the [replace specification](https://clojuredocs.org/clojure.string/replace). e.g. \"foo_$1_bar\" " [target-dir file-filter pattern pattern-replacement] - (log/debug "Rename files and directories in " target-dir " , from `" pattern "` to `" pattern-replacement "`") + (log/debug "Rename files and directories in " + target-dir + " , from `" + pattern + "` to `" + pattern-replacement + "`") (let [pattern (remove-trailing-separator (str pattern)) - pattern-replacement (remove-trailing-separator (str pattern-replacement))] + pattern-replacement (remove-trailing-separator (str + pattern-replacement))] (loop [iterations-left 30] (if (> iterations-left 0) - (when (rename-recursively-attempt target-dir file-filter pattern pattern-replacement) + (when (rename-recursively-attempt target-dir + file-filter + pattern + pattern-replacement) (recur (dec iterations-left))) (log/warn "Infinite loop detected during renaming"))))) @@ -324,12 +305,10 @@ * `pattern` is a regular expression as described in [java doc](https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)) " [target-dir pattern] (log/debug "Create files-map for " target-dir " with parameter " pattern) - (->> (search-files target-dir - pattern) + (->> (search-files target-dir pattern) (filter is-existing-file?) - (map (fn [filename] - [(str (absolutize filename)) - (read-file (absolutize filename))])) + (map (fn [filename] [(str (absolutize filename)) + (read-file (absolutize filename))])) (into {}))) (defn delete-files-starting-with @@ -361,9 +340,9 @@ * none Returns the string of the directory path" [] - (let [tmp-dir (apply create-dir-path [(conf/read-param [:tests :tmp-dirs] - "tmp/tests") - (str (uuid/time-based-uuid))])] + (let [tmp-dir (apply create-dir-path + [(conf/read-param [:tests :tmp-dirs] "tmp/tests") + (str (uuid/time-based-uuid))])] (fs/create-dirs tmp-dir) tmp-dir)) @@ -373,20 +352,17 @@ * `dirs` sequence of string of directories" [dirs] (apply vector - (mapcat (fn [sub-dir] - (let [sub-dir-rpath (absolutize sub-dir)] - (when (directory-exists? sub-dir-rpath) - [sub-dir-rpath]))) - dirs))) + (mapcat (fn [sub-dir] + (let [sub-dir-rpath (absolutize sub-dir)] + (when (directory-exists? sub-dir-rpath) [sub-dir-rpath]))) + dirs))) (defn empty-path? "Is the directory empty Params: * `dir` the directory to search in" [dir] - (boolean - (and (fs/directory? dir) - (empty? (fs/list-dir dir))))) + (boolean (and (fs/directory? dir) (empty? (fs/list-dir dir))))) (defn create-tmp-edn "Create a temporary file with edn extension" @@ -400,11 +376,11 @@ This function has a trick to print exception and its stacktrace" [data] (let [filename (create-tmp-edn) - formatted-data (with-out-str (prn data)) ;; Important to print exception properly - ] + formatted-data (with-out-str (prn data)) ;; Important to print + ;; exception properly + ] (spit filename formatted-data) - (format "See file `%s` for details" - (absolutize filename)))) + (format "See file `%s` for details" (absolutize filename)))) (defn file-name "Return the file name without the path" @@ -415,9 +391,7 @@ "Write `content` in the file `target-file`" [content target-filename] (log/trace (str "Writing file `" target-filename "`, content=" content)) - (try - (spit target-filename content) - (catch Exception e - (throw (ex-info "Impossible to write the file" - {:target-filename target-filename - :exception e}))))) + (try (spit target-filename content) + (catch Exception e + (throw (ex-info "Impossible to write the file" + {:target-filename target-filename, :exception e}))))) diff --git a/src/clj/automaton_core/adapters/java_properties.clj b/src/clj/automaton_core/adapters/java_properties.clj index cfbc7e3c..f079da43 100644 --- a/src/clj/automaton_core/adapters/java_properties.clj +++ b/src/clj/automaton_core/adapters/java_properties.clj @@ -1,16 +1,12 @@ -(ns automaton-core.adapters.java-properties - "Adapter to java properties") +(ns automaton-core.adapters.java-properties "Adapter to java properties") (defn get-java-properties "Get the java properties" [] - (into {} - (System/getProperties))) + (into {} (System/getProperties))) (defn get-java-property "Get a java property named `property-name`, if not found return `default-value`" ([property-name default-value] - (or (System/getProperty property-name) - default-value)) - ([property-name] - (System/getProperty property-name))) + (or (System/getProperty property-name) default-value)) + ([property-name] (System/getProperty property-name))) diff --git a/src/clj/automaton_core/adapters/schema.clj b/src/clj/automaton_core/adapters/schema.clj index cb9eec0c..210111bc 100644 --- a/src/clj/automaton_core/adapters/schema.clj +++ b/src/clj/automaton_core/adapters/schema.clj @@ -1,9 +1,8 @@ (ns automaton-core.adapters.schema "Validate the data against the schema. Is a proxy for malli" - (:require - [malli.core :as m] - [malli.error :as me])) + (:require [malli.core :as malli] + [malli.error :as malli-error])) (defn schema-valid "Return true if the data is not matching the schema @@ -11,8 +10,7 @@ * `schema` schema to match * `data` data to check appliance to schema" [schema data] - (m/validate schema - data)) + (malli/validate schema data)) (defn schema-valid-or-throw "True or throw an exception if the data is not matching the schema. @@ -21,11 +19,10 @@ * `data` data to check appliance to schema * `msg` to send in the exception if thrown" [schema data msg] - (when-not (schema-valid schema - data) + (when-not (schema-valid schema data) (throw (ex-info msg - {:data data + {:data data, :reason (-> schema - (m/explain data) - (me/humanize))}))) + (malli/explain data) + (malli-error/humanize))}))) data) diff --git a/src/clj/automaton_core/adapters/version.clj b/src/clj/automaton_core/adapters/version.clj index deeaf1a0..2dd4cc3b 100644 --- a/src/clj/automaton_core/adapters/version.clj +++ b/src/clj/automaton_core/adapters/version.clj @@ -1,11 +1,9 @@ (ns automaton-core.adapters.version "Version of an application" - (:require - [automaton-core.adapters.edn-utils :as edn-utils] - [automaton-core.adapters.files :as files])) + (:require [automaton-core.adapters.edn-utils :as edn-utils] + [automaton-core.adapters.files :as files])) -(def release - :release) +(def release :release) (def version-filename "The name of the version file to be found in ready to be deployed application" @@ -13,8 +11,8 @@ (defn slurp-version "Get the version of the current application, if not found a local dev value is given" - ([file-path] (if (files/is-existing-file? (str file-path version-filename)) - (edn-utils/read-edn-or-nil (str file-path version-filename)) - {release "local-dev"})) - ([] - (slurp-version ""))) + ([file-path] + (if (files/is-existing-file? (str file-path version-filename)) + (edn-utils/read-edn-or-nil (str file-path version-filename)) + {release "local-dev"})) + ([] (slurp-version ""))) diff --git a/src/clj/automaton_core/configuration.clj b/src/clj/automaton_core/configuration.clj index fbaeb798..29c10612 100644 --- a/src/clj/automaton_core/configuration.clj +++ b/src/clj/automaton_core/configuration.clj @@ -14,44 +14,42 @@ For a parameter `p`: * Create the parameter, in the current implementation, in the `util/conf.clj` * Read the parameter with `conf/read-param`" - (:require - [automaton-core.configuration.protocol :as prot] - [automaton-core.configuration.simple-files :as simple-files] - [automaton-core.log :as log] - [mount.core :refer [defstate in-cljc-mode]])) + (:require [automaton-core.configuration.protocol :as configuration-prot] + [automaton-core.configuration.simple-files :as simple-files] + [automaton-core.log :as log] + [mount.core :refer [defstate in-cljc-mode]])) ;; Force the use of `cljc mode` in mount library, so call to `@` will work (in-cljc-mode) -(defn start-conf [] - (try - (log/info "Starting configuration component") - (let [conf (simple-files/make-simple-conf)] - (log/trace "Configuration component is started") - conf) - (catch Throwable e - (log/fatal (ex-info "Configuration component failed" - {:error e})) - (throw e)))) +(defn start-conf + [] + (try (log/info "Starting configuration component") + (let [conf (simple-files/make-simple-conf)] + (log/trace "Configuration component is started") + conf) + (catch Throwable e + (log/fatal (ex-info "Configuration component failed" {:error e})) + (throw e)))) -(defn stop-conf [] - (log/debug "Stop configuration component")) +(defn stop-conf [] (log/debug "Stop configuration component")) -(defstate conf-state - :start (start-conf) - :stop (stop-conf)) +(defstate conf-state :start (start-conf) :stop (stop-conf)) (defn read-param ([key-path default-value] - (cond (not (vector? key-path)) (do - (log/warn-format "Key path should be a vector. I found " key-path) - default-value) - (instance? mount.core.NotStartedState @conf-state) (do - (log/warn-format "Unexpected error in configuration, component configuration is not started" @conf-state) - default-value) - :else (let [value (prot/read-conf-param @conf-state key-path)] - (log/trace "Read key-path " key-path " = " value) - (or value - default-value)))) - ([key-path] - (read-param key-path nil))) + (cond + (not (vector? key-path)) + (do (log/warn-format "Key path should be a vector. I found " key-path) + default-value) + (instance? mount.core.NotStartedState @conf-state) + (do + (log/warn-format + "Unexpected error in configuration, component configuration is not started" + @conf-state) + default-value) + :else (let [value (configuration-prot/read-conf-param @conf-state + key-path)] + (log/trace "Read key-path " key-path " = " value) + (or value default-value)))) + ([key-path] (read-param key-path nil))) diff --git a/src/clj/automaton_core/configuration/edn_read.clj b/src/clj/automaton_core/configuration/edn_read.clj index b6a9de78..aa39adb6 100644 --- a/src/clj/automaton_core/configuration/edn_read.clj +++ b/src/clj/automaton_core/configuration/edn_read.clj @@ -1,10 +1,9 @@ (ns automaton-core.configuration.edn-read "Specific read edn for configuration We cannot use edn-utils there, as that namespace would create a cycle dependancy" - (:require - [automaton-core.log :as log] - [babashka.fs :as fs] - [clojure.edn :as edn])) + (:require [automaton-core.log :as log] + [babashka.fs :as fs] + [clojure.edn :as edn])) (defn read-edn "Read the `.edn` file, @@ -16,16 +15,14 @@ * `file` could be a string representing the name of the file to load or a (io/resource) object representing the name of the file to load" [edn-filename] - (let [edn-filename (when edn-filename - (str (fs/absolutize edn-filename))) + (let [edn-filename (when edn-filename (str (fs/absolutize edn-filename))) _ (log/trace "Load file:" edn-filename) - edn-content (try - (slurp edn-filename) - (catch Exception _ - (log/warn-format "Unable to load the file `%s`" edn-filename) - nil))] - (try - (edn/read-string edn-content) - (catch Exception _ - (log/warn-format "File `%s` is not a valid edn" edn-filename) - nil)))) + edn-content (try (slurp edn-filename) + (catch Exception _ + (log/warn-format "Unable to load the file `%s`" + edn-filename) + nil))] + (try (edn/read-string edn-content) + (catch Exception _ + (log/warn-format "File `%s` is not a valid edn" edn-filename) + nil)))) diff --git a/src/clj/automaton_core/configuration/protocol.clj b/src/clj/automaton_core/configuration/protocol.clj index e75e5e42..9d789e82 100644 --- a/src/clj/automaton_core/configuration/protocol.clj +++ b/src/clj/automaton_core/configuration/protocol.clj @@ -1,4 +1,5 @@ (ns automaton-core.configuration.protocol) (defprotocol Conf - (read-conf-param [this key-path] "Read the value of key")) + (read-conf-param [this key-path] + "Read the value of key")) diff --git a/src/clj/automaton_core/configuration/simple_files.clj b/src/clj/automaton_core/configuration/simple_files.clj index 4ed47673..d6d7102f 100644 --- a/src/clj/automaton_core/configuration/simple_files.clj +++ b/src/clj/automaton_core/configuration/simple_files.clj @@ -3,17 +3,13 @@ Data can be set in two files: * one set in `heph-common-conf` java property for all values not specific to an environment * one set in `heph-conf` java property for all values specific to that environment" - (:require - [automaton-core.adapters.java-properties :as java-properties] - [automaton-core.configuration.edn-read :as conf-edn-read] - [automaton-core.configuration.protocol :as protocol])) + (:require [automaton-core.adapters.java-properties :as java-properties] + [automaton-core.configuration.edn-read :as conf-edn-read] + [automaton-core.configuration.protocol :as configuration-prot])) -(defrecord SimpleConf - [config-map] - protocol/Conf - (read-conf-param [_this key-path] - (get-in config-map - key-path))) +(defrecord SimpleConf [config-map] + configuration-prot/Conf + (read-conf-param [_this key-path] (get-in config-map key-path))) (defn- load-conf [property-name] diff --git a/src/clj/automaton_core/dev.clj b/src/clj/automaton_core/dev.clj index b4bcc135..83d4f6b2 100644 --- a/src/clj/automaton_core/dev.clj +++ b/src/clj/automaton_core/dev.clj @@ -1,24 +1,13 @@ (ns automaton-core.dev "Will be `refer :all` in the subproject `user` namespace, default namepsace for subproject REPL" - (:require - [clj-memory-meter.core :as mm] + (:require [clj-memory-meter.core :as mm] + [automaton-core.repl :as repl])) - [automaton-core.repl :as repl])) - -(defn start - "Start repl" - [& _args] - (repl/start-repl)) +(defn start "Start repl" [& _args] (repl/start-repl)) #_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]} -(defn go - "starts all states defined by defstate" - [] - (start) - :ready) +(defn go "starts all states defined by defstate" [] (start) :ready) ;; See https://github.com/clojure-goes-fast/clj-memory-meter, for details #_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]} -(defn measure-time-sample - [] - (mm/measure "hello world")) +(defn measure-time-sample [] (mm/measure "hello world")) diff --git a/src/clj/automaton_core/log/be_log.clj b/src/clj/automaton_core/log/be_log.clj index 926d1db0..10aea5dc 100644 --- a/src/clj/automaton_core/log/be_log.clj +++ b/src/clj/automaton_core/log/be_log.clj @@ -3,22 +3,22 @@ Macros in this namespace to log are chosen from `automaton-core.log`. Current structure is generic for logging level, as they are the same right now in sense of this proxy. In future it may develop if needed to e.g. have the same number of macros as in `automaton-core.log`." - (:require - [automaton-core.log.be-registry :as log-registry] - [automaton-core.log.tracking.be-error-tracking :as exs])) + (:require [automaton-core.log.be-registry :as log-be-registry] + [automaton-core.log.tracking.be-error-tracking :as exs])) -(defn log-init! [{:keys [dsn env]}] - (exs/init-error-tracking! {:dsn dsn - :env env})) +(defn log-init! + [{:keys [dsn env]}] + (exs/init-error-tracking! {:dsn dsn, :env env})) (defn- logger-ids-to-logger-fns "Based on logger-id chooses from registered strategies which logging function to use." [logger-ids] (reduce (fn [acc logger-id] - (conj acc (get-in automaton-core.log.be-registry/strategies-registry - [logger-id :impl]))) - [] - logger-ids)) + (conj acc + (get-in log-be-registry/strategies-registry + [logger-id :impl]))) + [] + logger-ids)) (defmacro log [logger-ids level & message] @@ -28,16 +28,14 @@ (defmacro log-exception [logger-ids level exception & additional-message] - (when additional-message - `(log ~logger-ids ~level ~@additional-message)) + (when additional-message `(log ~logger-ids ~level ~@additional-message)) (let [ns *ns* log-fns (logger-ids-to-logger-fns logger-ids)] `((juxt ~@log-fns) ~ns ~level ~exception))) (defmacro log-data [logger-ids level data & additional-message] - (when additional-message - `(log ~logger-ids level ~@additional-message)) + (when additional-message `(log ~logger-ids level ~@additional-message)) (let [ns *ns* log-fns (logger-ids-to-logger-fns logger-ids)] `((juxt ~@log-fns) ~ns ~level ~data))) diff --git a/src/clj/automaton_core/log/be_registry.clj b/src/clj/automaton_core/log/be_registry.clj index 758eaa2a..686d9ea5 100644 --- a/src/clj/automaton_core/log/be_registry.clj +++ b/src/clj/automaton_core/log/be_registry.clj @@ -1,26 +1,23 @@ (ns automaton-core.log.be-registry "List of all known backend strategies" - (:require - [automaton-core.log.registry :as log-registry] - [automaton-core.log.impl.log4j2] - [automaton-core.log.tracking.be-error-tracking])) + (:require [automaton-core.log.registry :as log-registry] + [automaton-core.log.impl.log4j2] + [automaton-core.log.tracking.be-error-tracking])) -(defn no-op-fn [& _] - nil) +(defn no-op-fn [& _] nil) -(defn simple-print - [_ns _level & msg] - (apply println msg)) +(defn simple-print [_ns _level & msg] (apply println msg)) (def strategies-registry "List of predefined strategies Look at clj and cljs implementations to have an understanding of that strategies implementation which may be different on both technologies. For instance, `:text-based` will be based on log4j2 on backedn and console on frontend" - {::log-registry/print {:description "Simple print" - :impl simple-print} - ::log-registry/text-based {:description "Basic one - sends everything to flatten text (js/console for clojurescript and log4j2 for clojure)" - :impl automaton-core.log.impl.log4j2/log-fn} - ::log-registry/no-op {:description "Deactivate that log" - :impl no-op-fn} - ::log-registry/error-tracking {:description "For monitoring exceptions in the application" - :impl automaton-core.log.tracking.be-error-tracking/log-fn}}) + {::log-registry/print {:description "Simple print", :impl simple-print}, + ::log-registry/text-based + {:description + "Basic one - sends everything to flatten text (js/console for clojurescript and log4j2 for clojure)", + :impl automaton-core.log.impl.log4j2/log-fn}, + ::log-registry/no-op {:description "Deactivate that log", :impl no-op-fn}, + ::log-registry/error-tracking + {:description "For monitoring exceptions in the application", + :impl automaton-core.log.tracking.be-error-tracking/log-fn}}) diff --git a/src/clj/automaton_core/log/impl/log4j2.clj b/src/clj/automaton_core/log/impl/log4j2.clj index 7f4cb868..45768bdf 100644 --- a/src/clj/automaton_core/log/impl/log4j2.clj +++ b/src/clj/automaton_core/log/impl/log4j2.clj @@ -3,9 +3,9 @@ Set to log4j2 [check setup in](clojure/deps.edn) For more information read docs/tutorial/logging.md" - (:require - [automaton-core.utils.pretty-print :as p] - [clojure.tools.logging :as l])) + (:require [automaton-core.utils.pretty-print :as pretty-print] + [clojure.tools.logging :as l])) -(defn log-fn [ns level & message] - (l/log ns level nil (p/seq->string message))) +(defn log-fn + [ns level & message] + (l/log ns level nil (pretty-print/seq->string message))) diff --git a/src/clj/automaton_core/log/log4j2.clj b/src/clj/automaton_core/log/log4j2.clj index 28870ef3..a99a4fb4 100644 --- a/src/clj/automaton_core/log/log4j2.clj +++ b/src/clj/automaton_core/log/log4j2.clj @@ -3,22 +3,17 @@ Set to log4j2 [check setup in](clojure/deps.edn) For more information read docs/tutorial/logging.md" - (:require - [clojure.pprint :as pp] - [clojure.string :as str] - - [clojure.tools.logging :as l] - - [automaton-core.adapters.string :as bas])) + (:require [automaton-core.adapters.string :as bas] + [clojure.pprint :as pp] + [clojure.string :as str] + [clojure.tools.logging :as l])) (defn prettify-elt "Prepare the element `elt` to display log as text in the console Params: * `elt` data to show, which type will be checked" [elt] - (if (or (map? elt) - (set? elt) - (vector? elt)) + (if (or (map? elt) (set? elt) (vector? elt)) (-> elt pp/pprint with-out-str @@ -27,11 +22,6 @@ (defn prettify [message] - (if (seqable? message) - (str/join "" - (map prettify-elt - message)) - message)) + (if (seqable? message) (str/join "" (map prettify-elt message)) message)) -(defn log-fn [ns level & message] - (l/log ns level nil (prettify message))) +(defn log-fn [ns level & message] (l/log ns level nil (prettify message))) diff --git a/src/clj/automaton_core/log/tracking/be_error_tracking.clj b/src/clj/automaton_core/log/tracking/be_error_tracking.clj index 5592e7da..1edfa879 100644 --- a/src/clj/automaton_core/log/tracking/be_error_tracking.clj +++ b/src/clj/automaton_core/log/tracking/be_error_tracking.clj @@ -4,23 +4,14 @@ (defn init-error-tracking! [{:keys [dsn env]}] - (sentry/init-sentry! - {:dsn dsn - :env env})) + (sentry/init-sentry! {:dsn dsn, :env env})) -(defn log-fn [ns level & message] - (let [context (if (map? (first message)) - (merge (first message) - {:ns ns}) - {:ns ns}) - message (if (map? (first message)) - (rest message) - message)] - (if (or (= level :error) - (= level :fatal)) - (sentry/send-event! {:message message - :level level - :context context}) - (sentry/send-breadcrumb! {:message message - :level level - :context context})))) +(defn log-fn + [ns level & message] + (let [context + (if (map? (first message)) (merge (first message) {:ns ns}) {:ns ns}) + message (if (map? (first message)) (rest message) message)] + (if (or (= level :error) (= level :fatal)) + (sentry/send-event! {:message message, :level level, :context context}) + (sentry/send-breadcrumb! + {:message message, :level level, :context context})))) diff --git a/src/clj/automaton_core/log/tracking/be_sentry.clj b/src/clj/automaton_core/log/tracking/be_sentry.clj index 9f39a275..1bb1ea8f 100644 --- a/src/clj/automaton_core/log/tracking/be_sentry.clj +++ b/src/clj/automaton_core/log/tracking/be_sentry.clj @@ -1,13 +1,11 @@ (ns automaton-core.log.tracking.be-sentry "Sentry backend implementation" - (:require - [automaton-core.utils.map :as m] - [sentry-clj.core :as sentry] - [automaton-core.utils.pretty-print :as p] - [automaton-core.log.tracking.sentry :as asentry]) - (:import - [io.sentry Breadcrumb Sentry SentryLevel] - [java.util Date HashMap Map])) + (:require [automaton-core.utils.map :as utils-map] + [sentry-clj.core :as sentry] + [automaton-core.utils.pretty-print :as pretty-print] + [automaton-core.log.tracking.sentry :as asentry]) + (:import [io.sentry Breadcrumb Sentry SentryLevel] + [java.util Date HashMap Map])) (defn- keyword->level "Converts a keyword into an event level." @@ -22,19 +20,15 @@ (defn- map->breadcrumb "Converts a map into a Breadcrumb." - ^Breadcrumb - [{:keys [type level message category data timestamp]}] + ^Breadcrumb [{:keys [type level message category data timestamp]}] (let [breadcrumb (if timestamp (Breadcrumb. ^Date timestamp) (Breadcrumb.))] - (when type - (.setType breadcrumb type)) - (when level - (.setLevel breadcrumb (keyword->level level))) - (when message - (.setMessage breadcrumb message)) - (when category - (.setCategory breadcrumb category)) + (when type (.setType breadcrumb type)) + (when level (.setLevel breadcrumb (keyword->level level))) + (when message (.setMessage breadcrumb message)) + (when category (.setCategory breadcrumb category)) (when data - (doseq [[k v] (m/map-util-hashmappify-vals data #(HashMap. ^Map %))] + (doseq [[k v] (utils-map/map-util-hashmappify-vals data + #(HashMap. ^Map %))] (.setData breadcrumb k v))) breadcrumb)) @@ -42,15 +36,16 @@ "Sends breadcrumb, which will not be shown in sentry until event is sent. You can read more here: https://docs.sentry.io/platforms/java/enriching-events/breadcrumbs/" [{:keys [message level context]}] - (Sentry/addBreadcrumb (map->breadcrumb {:message (p/seq->string message) - :level level + (Sentry/addBreadcrumb (map->breadcrumb {:message (pretty-print/seq->string + message), + :level level, :data context}))) (defn send-event! "Sends an event that is registered in sentry." [{:keys [message level context]}] - (sentry/send-event {:message (p/seq->string message) - :level level + (sentry/send-event {:message (pretty-print/seq->string message), + :level level, :extra context})) (defn init-sentry! @@ -58,6 +53,6 @@ 'development' as an environment is ignored, so no event is sent from it." [{:keys [dsn env]}] (sentry/init! dsn - {:environment env - :before-send-fn (fn [event _] - (asentry/silence-development-events event))})) + {:environment env, + :before-send-fn + (fn [event _] (asentry/silence-development-events event))})) diff --git a/src/clj/automaton_core/os/code_formatter.clj b/src/clj/automaton_core/os/code_formatter.clj new file mode 100644 index 00000000..b90e168f --- /dev/null +++ b/src/clj/automaton_core/os/code_formatter.clj @@ -0,0 +1,23 @@ +(ns automaton-core.os.code-formatter + "Format code + Proxy to [zprint](https://github.com/kkinnear/zprint)" + (:require [automaton-core.adapters.files :as files] + [automaton-core.adapters.commands :as cmds] + [automaton-core.adapters.time :as time] + [clojure.string :as str])) + +(defn format-file + "Format the `clj` or `edn` file + Params: + * `filename` to format + * `header` (optional) is written at the top of the file" + ([filename header] + (let [format-content (slurp filename)] + (files/spit-file filename + (apply str + [(when-not (str/blank? header) + (print-str ";;" header (time/now-str) "\n")) + format-content])) + (cmds/exec-cmds [[["zprint" "-w" filename] {:dir ".", :out :string}]]))) + ([filename] (format-file filename nil))) + diff --git a/src/clj/automaton_core/repl.clj b/src/clj/automaton_core/repl.clj index d58c262f..1f96706c 100644 --- a/src/clj/automaton_core/repl.clj +++ b/src/clj/automaton_core/repl.clj @@ -2,32 +2,23 @@ "REPL component Design decision: * The repl could have pushed to dev, but leaving it here allows to remotely connect to the remote repl, like la or production" - (:require - [automaton-core.adapters.files :as files] - [automaton-core.configuration :as conf] - [automaton-core.log :as log] - [cider.nrepl :as nrepl-mw] - [clojure.core.async :refer [ (files/search-files "" (str "**" nrepl-port-filename)) - (files/delete-files)) - (stop-repl repl-port)))))) + (reset! repl {:nrepl-port repl-port, + :repl (do (log/info "nrepl available on port " repl-port) + (println "repl port is available on:" repl-port) + (start-server :port repl-port + :handler (custom-nrepl-handler + middleware)))}) + (.addShutdownHook + (Runtime/getRuntime) + (Thread. #(do (log/info "SHUTDOWN in progress, stop repl on port `" + repl-port + "`") + (-> (files/search-files "" (str "**" nrepl-port-filename)) + (files/delete-files)) + (stop-repl repl-port)))))) (defn start-repl "Start repl, setup and catch errors" [] (try - (start-repl* {:middleware (conj nrepl-mw/cider-middleware 'refactor-nrepl.middleware/wrap-refactor)}) + (start-repl* {:middleware (conj nrepl-mw/cider-middleware + 'refactor-nrepl.middleware/wrap-refactor)}) :started - (catch Exception e - (log/error (ex-info "Uncaught exception" {:error e}))))) + (catch Exception e (log/error (ex-info "Uncaught exception" {:error e}))))) (defn -main "Entry point for simple / emergency repl" diff --git a/src/clj/automaton_core/utils/date.clj b/src/clj/automaton_core/utils/date.clj index 11ed6b0c..09ddab57 100644 --- a/src/clj/automaton_core/utils/date.clj +++ b/src/clj/automaton_core/utils/date.clj @@ -1,11 +1,7 @@ -(ns automaton-core.utils.date - "Utility function for date management") +(ns automaton-core.utils.date "Utility function for date management") -(def year-format - (java.text.SimpleDateFormat. "yyyy")) +(def year-format (java.text.SimpleDateFormat. "yyyy")) (defn this-year - ([date] - (.format year-format date)) - ([] - (this-year (java.util.Date.)))) + ([date] (.format year-format date)) + ([] (this-year (java.util.Date.)))) diff --git a/src/clj/automaton_core/utils/pretty_print.clj b/src/clj/automaton_core/utils/pretty_print.clj index e8f3de98..0e536522 100644 --- a/src/clj/automaton_core/utils/pretty_print.clj +++ b/src/clj/automaton_core/utils/pretty_print.clj @@ -8,9 +8,7 @@ Params: * `elt` data to show, which type will be checked" [elt] - (if (or (map? elt) - (set? elt) - (vector? elt)) + (if (or (map? elt) (set? elt) (vector? elt)) (-> elt pp/pprint with-out-str @@ -20,8 +18,4 @@ (defn seq->string "Returns string from sequence, that is readable in write outputs." [message] - (if (seqable? message) - (apply str "" - (map one-liner-print - message)) - message)) + (if (seqable? message) (apply str "" (map one-liner-print message)) message)) diff --git a/src/cljc/automaton_core/adapters/re.cljc b/src/cljc/automaton_core/adapters/re.cljc index 0952677a..0b404008 100644 --- a/src/cljc/automaton_core/adapters/re.cljc +++ b/src/cljc/automaton_core/adapters/re.cljc @@ -15,9 +15,7 @@ (defn stringify [re] #?(:clj (str re) - :cljs (if (string? re) - re - (aas/remove-first-last-character (str re))))) + :cljs (if (string? re) re (aas/remove-first-last-character (str re))))) (defn assemble-re "Assemble regular expressions together @@ -46,13 +44,8 @@ (loop [[re optional? & nexts] res assembled ""] (let [re (stringify re) - assembled-re (str assembled - (if optional? - (str re "?") - re))] + assembled-re (str assembled (if optional? (str re "?") re))] (if nexts - (recur nexts - assembled-re) + (recur nexts assembled-re) (re-pattern (str prefix assembled-re suffix)))))) - ([res] - (assemble-re-optional res nil nil))) + ([res] (assemble-re-optional res nil nil))) diff --git a/src/cljc/automaton_core/adapters/string.cljc b/src/cljc/automaton_core/adapters/string.cljc index 4dd9c1dc..e325ec43 100644 --- a/src/cljc/automaton_core/adapters/string.cljc +++ b/src/cljc/automaton_core/adapters/string.cljc @@ -4,19 +4,14 @@ (defn remove-last-character "Remove the last character of a string" [s] - (let [s (str s)] - (subs s 0 (max 0 (- (count s) - 1))))) + (let [s (str s)] (subs s 0 (max 0 (- (count s) 1))))) (defn remove-first-last-character "Remove the first and last character of a string" [s] (let [s (str s) count-s (count s)] - (if (< 2 count-s) - (subs s 1 (max 0 (- (count s) - 1))) - ""))) + (if (< 2 count-s) (subs s 1 (max 0 (- (count s) 1))) ""))) (def ellipsis "...") @@ -26,23 +21,18 @@ * `s` string to limit * `limit` maximum numbers of character of the resulting string, with prefix and suffix included, with an ellipsis of string s if necessary * `on-ellipsis` a function executed when the ellipsis is done" - ([s limit] - (limit-length s limit nil nil identity)) + ([s limit] (limit-length s limit nil nil identity)) ([s limit prefix suffix on-ellipsis] (let [line (str prefix s suffix)] (if (<= (count line) limit) line - (do - (on-ellipsis s) - (apply str - (concat prefix - (take (- limit - (count ellipsis) - (count prefix) - (count suffix)) - s) - ellipsis - suffix))))))) + (do (on-ellipsis s) + (apply str + (concat + prefix + (take (- limit (count ellipsis) (count prefix) (count suffix)) s) + ellipsis + suffix))))))) (defn remove-trailing-character "Remove last character if it is matching char @@ -51,7 +41,9 @@ * `char` a character to compare to last character of `s`" [s char] (if (= char (last s)) - (subs s 0 (-> s - count - dec)) + (subs s + 0 + (-> s + count + dec)) s)) diff --git a/src/cljc/automaton_core/i18n/dict/text.cljc b/src/cljc/automaton_core/i18n/dict/text.cljc index a5b76ccd..edd45897 100644 --- a/src/cljc/automaton_core/i18n/dict/text.cljc +++ b/src/cljc/automaton_core/i18n/dict/text.cljc @@ -5,5 +5,4 @@ (def dict "Contains all translations internally needed for `automaton-core`" - {:en {} - :fr {}}) + {:en {}, :fr {}}) diff --git a/src/cljc/automaton_core/i18n/language.cljc b/src/cljc/automaton_core/i18n/language.cljc index c39a5331..9b592c66 100644 --- a/src/cljc/automaton_core/i18n/language.cljc +++ b/src/cljc/automaton_core/i18n/language.cljc @@ -4,45 +4,36 @@ It is only a place for language description, not to tell where it is supposed to be used See cust-app themselves to know what language they use" - (:require - [automaton-core.utils.map :as utils-map] - [clojure.set :as set])) + (:require [automaton-core.utils.map :as utils-map] + [clojure.set :as set])) (defprotocol Languages - (language [this lang-id] "return the language\nParams:\n * `lang-id`: language id") - (languages [this] "return the list of known languages") - (languages-ids [this] "Set of known ids (set of keywords)") - (dict-languages-ids [this] "Set of known language ids keywords")) + (language [this lang-id] + "return the language\nParams:\n * `lang-id`: language id") + (languages [this] + "return the list of known languages") + (languages-ids [this] + "Set of known ids (set of keywords)") + (dict-languages-ids [this] + "Set of known language ids keywords")) -(defrecord AutomatonCoreLanguages - [languages] +(defrecord AutomatonCoreLanguages [languages] Languages - (language [_ lang-id] - (get languages lang-id)) - (languages [_] - languages) - (languages-ids [_] - (set - (keys languages))) - (dict-languages-ids [_] - (set - (map first (filter (fn [[_ language]] - (:core-dict? language)) - languages))))) + (language [_ lang-id] (get languages lang-id)) + (languages [_] languages) + (languages-ids [_] (set (keys languages))) + (dict-languages-ids [_] + (set (map first + (filter (fn [[_ language]] (:core-dict? language)) languages))))) (def ^:private core-languages-dict "Defines list of known language, the keys are internal identifiers and values are defined with: * `core-dict?` tells if that language should be used in dictionary of autamaton-core. This value is a decision, it will be used to check that the dictionary contains all of them * `ui-text` the text to show in UI as an identifier of the language. * `desc` description of the language" - {:fr {:core-dict? true - :ui-text "FR" - :desc "Français"} - :en {:core-dict? true - :ui-text "EN" - :desc "English"} - :pl {:ui-text "PL" - :desc "Polski"}}) + {:fr {:core-dict? true, :ui-text "FR", :desc "Français"}, + :en {:core-dict? true, :ui-text "EN", :desc "English"}, + :pl {:ui-text "PL", :desc "Polski"}}) (defn merge-languages-map "Merge maps in the argument order, so all their data are merged and the ones on the left are lower priority @@ -53,11 +44,10 @@ * sequence of languages matching a language id to the language description" [& selected-languages-seq] (let [languages-ids (apply set/intersection - (mapv (comp set keys) - selected-languages-seq)) + (mapv (comp set keys) selected-languages-seq)) languages (-> (apply utils-map/deep-merge (map #(select-keys % languages-ids) - selected-languages-seq)) + selected-languages-seq)) utils-map/add-ids)] languages)) @@ -68,9 +58,8 @@ The final map consists in the languages defined in both `selected-languages` `core-lang/base-languages` The language data map are merged, see `merge-languages-map` for details" [& selected-languages-seq] - (->AutomatonCoreLanguages (apply merge-languages-map - core-languages-dict - selected-languages-seq))) + (->AutomatonCoreLanguages + (apply merge-languages-map core-languages-dict selected-languages-seq))) (def core-languages "Languages available in `automaton-core`, instance of `Languages`" diff --git a/src/cljc/automaton_core/i18n/missing_translation_report.cljc b/src/cljc/automaton_core/i18n/missing_translation_report.cljc index ac18d9f3..53226b87 100644 --- a/src/cljc/automaton_core/i18n/missing_translation_report.cljc +++ b/src/cljc/automaton_core/i18n/missing_translation_report.cljc @@ -1,22 +1,20 @@ (ns automaton-core.i18n.missing-translation-report "Helper functions to test correctness of translation data including dictionaries" - (:require - [automaton-core.utils.map :as crusher] - [clojure.set :refer [union]])) + (:require [automaton-core.utils.map :as utils-map] + [clojure.set :refer [union]])) (defn language-report "For all keys of a dictionnary, return the list of languages set `expected-languages` is the languages sequence the report is limited to" [dictionary expected-languages] (let [filtered-dictionary (select-keys dictionary expected-languages)] - (apply merge-with union - (map (fn [[language dict-map]] - (into {} - (map (fn [v] - [v #{language}]) - (keys - (crusher/crush dict-map))))) - filtered-dictionary)))) + (apply merge-with + union + (map (fn [[language dict-map]] + (into {} + (map (fn [v] [v #{language}]) + (keys (utils-map/crush dict-map))))) + filtered-dictionary)))) (defn key-with-missing-languages "Return a map with the path to a translation, with the list of existing languages @@ -27,5 +25,4 @@ (filter (fn [[k v]] (and (not (contains? key-set-exceptions k)) (not= v expected-languages))) - (language-report dictionary - expected-languages)))) + (language-report dictionary expected-languages)))) diff --git a/src/cljc/automaton_core/i18n/translator.cljc b/src/cljc/automaton_core/i18n/translator.cljc index 634161c6..372eea96 100644 --- a/src/cljc/automaton_core/i18n/translator.cljc +++ b/src/cljc/automaton_core/i18n/translator.cljc @@ -1,6 +1,7 @@ -(ns automaton-core.i18n.translator - "Protocol for translation logic") +(ns automaton-core.i18n.translator "Protocol for translation logic") (defprotocol Translator - (default-languages [this] "sequence of ids of the default languages") - (translate [this lang-ids tr-id resources] "translate the `:tr-id` with the resources as parameters (first resource is %1, second is %2, ...), trying to translate with first language lang-ids, then second, ...")) + (default-languages [this] + "sequence of ids of the default languages") + (translate [this lang-ids tr-id resources] + "translate the `:tr-id` with the resources as parameters (first resource is %1, second is %2, ...), trying to translate with first language lang-ids, then second, ...")) diff --git a/src/cljc/automaton_core/i18n/translator/tempura.cljc b/src/cljc/automaton_core/i18n/translator/tempura.cljc index a6bbe8c3..8ca1022e 100644 --- a/src/cljc/automaton_core/i18n/translator/tempura.cljc +++ b/src/cljc/automaton_core/i18n/translator/tempura.cljc @@ -3,27 +3,26 @@ Is an adapter for translation in `automaton-core`, so no web related technology is mentionned there, even if tempura provides them. It will be the job of `automton-web` to provide that features" - (:require - [automaton-core.i18n.dict.text :as core-dict] - [automaton-core.i18n.translator :as core-translator] - [automaton-core.log :as log] - [automaton-core.utils.map :as utils-map] - [taoensso.tempura :as tempura])) + (:require [automaton-core.i18n.dict.text :as core-dict] + [automaton-core.i18n.translator :as core-translator] + [automaton-core.log :as log] + [automaton-core.utils.map :as utils-map] + [taoensso.tempura :as tempura])) (def tempura-missing-text "Necessary for tempura, a missing key is expected for all languages marked with `:core-dict?` in `automaton-core.i18n.language`" - {:en {:missing "The text is missing! :( Please let us know at info@hephaistox.com"} - :fr {:missing "Le texte est manquant! :( Veuillez nous en informer à l'adresse info@hephaistox.com"}}) + {:en {:missing + "The text is missing! :( Please let us know at info@hephaistox.com"}, + :fr + {:missing + "Le texte est manquant! :( Veuillez nous en informer à l'adresse info@hephaistox.com"}}) (defn- append-dictionaries "Appends dictionaries Params: * `dicts` list of dictionaries to append together, the default keys for missing keys and the core dictionary are defaulted" [dicts] - (apply utils-map/deep-merge - tempura-missing-text - core-dict/dict - dicts)) + (apply utils-map/deep-merge tempura-missing-text core-dict/dict dicts)) (defn create-opts "Create the options for tempura/tr @@ -31,27 +30,26 @@ * `dicts` list of dictionaries to append together, the default keys for missing keys and the core dictionary are defaulted" [& dicts] (let [debug true ;; (= :dev (conf-core/read-param [:env])) - ] - {:dict (append-dictionaries dicts) - :cache-dict? (not debug) - :default-local :fr + ] + {:dict (append-dictionaries dicts), + :cache-dict? (not debug), + :default-local :fr, :cache-locales (not debug)})) -(defrecord TempuraTranslator - [opts main-langs] +(defrecord TempuraTranslator [opts main-langs] core-translator/Translator - - (default-languages [_] - main-langs) - - (translate [_ langs-id tr-id resources] - (let [locales (vec (concat langs-id main-langs)) - translated-text (tempura/tr opts - locales - [tr-id] - resources)] - (log/trace "Translate key `" tr-id "`,with locales `" locales "`, -> `" translated-text "`") - translated-text))) + (default-languages [_] main-langs) + (translate [_ langs-id tr-id resources] + (let [locales (vec (concat langs-id main-langs)) + translated-text (tempura/tr opts locales [tr-id] resources)] + (log/trace "Translate key `" + tr-id + "`,with locales `" + locales + "`, -> `" + translated-text + "`") + translated-text))) (defn make-translator "Build a TempuraTranslator diff --git a/src/cljc/automaton_core/log.cljc b/src/cljc/automaton_core/log.cljc index dae52123..cf9284c0 100644 --- a/src/cljc/automaton_core/log.cljc +++ b/src/cljc/automaton_core/log.cljc @@ -3,11 +3,11 @@ Logical order of logs is: trace -> debug -> info -> warn -> error -> fatal" - (:require - [automaton-core.log.strategy.static-ns-level :as log-static-ns-level-strategy] - [automaton-core.log.strategy :as log-strategy] - #?(:clj [automaton-core.log.be-log] - :cljs [automaton-core.log.fe-log])) + (:require [automaton-core.log.strategy.static-ns-level :as + log-static-ns-level-strategy] + [automaton-core.log.strategy :as log-strategy] + #?(:clj [automaton-core.log.be-log] + :cljs [automaton-core.log.fe-log])) #?(:cljs (:require-macros [automaton-core.log]))) (def stgy @@ -22,8 +22,8 @@ (defmacro trace "Records all of the application's behaviour details. Its purpose is primarily diagnostic, and it is more granular and finer than the DEBUG log level. When you need to know what happened in your application or the third-party libraries you're using, utilise this log level. The TRACE log level can be used to query code parameters or analyse algorithm steps." [& message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :trace)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :trace)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log ~logger-id# :trace ~@message) `(automaton-core.log.be-log/log ~logger-id# :trace ~@message)))) @@ -31,26 +31,38 @@ (defmacro trace-exception "Like trace, but focused on exceptions." [exception & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :trace)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :trace)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-exception ~logger-id# :trace ~exception ~@additional-message) - `(automaton-core.log.be-log/log-exception ~logger-id# :trace ~exception ~@additional-message)))) + `(automaton-core.log.fe-log/log-exception ~logger-id# + :trace + ~exception + ~@additional-message) + `(automaton-core.log.be-log/log-exception ~logger-id# + :trace + ~exception + ~@additional-message)))) (defmacro trace-data "Like trace, but first argument is expected to be a map with usefull more detailed data." [data & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :trace)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :trace)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-data ~logger-id# :trace ~data ~@additional-message) - `(automaton-core.log.be-log/log-data ~logger-id# :trace ~data ~@additional-message)))) + `(automaton-core.log.fe-log/log-data ~logger-id# + :trace + ~data + ~@additional-message) + `(automaton-core.log.be-log/log-data ~logger-id# + :trace + ~data + ~@additional-message)))) (defmacro trace-format "Like trace, but uses clojure format function, so first argument is string to translate and rest is arguments to supply it with." [fmt & args] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :trace)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :trace)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log-format ~logger-id# :trace ~fmt ~@args) `(automaton-core.log.be-log/log-format ~logger-id# :trace ~fmt ~@args)))) @@ -58,8 +70,8 @@ (defmacro debug "You are providing diagnostic information in a thorough manner with DEBUG. It's long and contains more information than you'll need when using the application. The DEBUG logging level is used to retrieve data that is required to debug, troubleshoot, or test an application. This guarantees that the application runs smoothly." [& message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :debug)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :debug)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log ~logger-id# :debug ~@message) `(automaton-core.log.be-log/log ~logger-id# :debug ~@message)))) @@ -67,26 +79,38 @@ (defmacro debug-exception "Like debug, but focused on exceptions." [exception & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :debug)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :debug)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-exception ~logger-id# :debug ~exception ~@additional-message) - `(automaton-core.log.be-log/log-exception ~logger-id# :debug ~exception ~@additional-message)))) + `(automaton-core.log.fe-log/log-exception ~logger-id# + :debug + ~exception + ~@additional-message) + `(automaton-core.log.be-log/log-exception ~logger-id# + :debug + ~exception + ~@additional-message)))) (defmacro debug-data "Like debug, but first argument is expected to be a map with usefull more detailed data." [data & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :debug)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :debug)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-data ~logger-id# :debug ~data ~@additional-message) - `(automaton-core.log.be-log/log-data ~logger-id# :debug ~data ~@additional-message)))) + `(automaton-core.log.fe-log/log-data ~logger-id# + :debug + ~data + ~@additional-message) + `(automaton-core.log.be-log/log-data ~logger-id# + :debug + ~data + ~@additional-message)))) (defmacro debug-format "Like debug, but uses clojure format function, so first argument is string to translate and rest is arguments to supply it with." [fmt & args] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :debug)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :debug)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log-format ~logger-id# :debug ~fmt ~@args) `(automaton-core.log.be-log/log-format ~logger-id# :debug ~fmt ~@args)))) @@ -94,8 +118,7 @@ (defmacro info "INFO messages are similar to how applications normally behave. They describe what occurred. For example, if a specific service was stopped or started, or if something was added to the database. During normal operations, these entries are unimportant. The information written in the INFO log is usually useful, and you don't have to do anything with it." [& message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :info)] + (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy *ns* :info)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log ~logger-id# :info ~@message) `(automaton-core.log.be-log/log ~logger-id# :info ~@message)))) @@ -103,26 +126,35 @@ (defmacro info-exception "Like info, but focused on exceptions." [exception & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :info)] + (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy *ns* :info)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-exception ~logger-id# :info ~exception ~@additional-message) - `(automaton-core.log.be-log/log-exception ~logger-id# :info ~exception ~@additional-message)))) + `(automaton-core.log.fe-log/log-exception ~logger-id# + :info + ~exception + ~@additional-message) + `(automaton-core.log.be-log/log-exception ~logger-id# + :info + ~exception + ~@additional-message)))) (defmacro info-data "Like info, but first argument is expected to be a map with usefull more detailed data." [data & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :info)] + (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy *ns* :info)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-data ~logger-id# :info ~data ~@additional-message) - `(automaton-core.log.be-log/log-data ~logger-id# :info ~data ~@additional-message)))) + `(automaton-core.log.fe-log/log-data ~logger-id# + :info + ~data + ~@additional-message) + `(automaton-core.log.be-log/log-data ~logger-id# + :info + ~data + ~@additional-message)))) (defmacro info-format "Like info, but uses clojure format function, so first argument is string to translate and rest is arguments to supply it with." [fmt & args] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :info)] + (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy *ns* :info)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log-format ~logger-id# :info ~fmt ~@args) `(automaton-core.log.be-log/log-format ~logger-id# :info ~fmt ~@args)))) @@ -130,8 +162,7 @@ (defmacro warn "When an unexpected application issue has been identified, the WARN log level is used. This indicates that you are unsure if the issue will recur or not. At this time, you may not notice any negative effects on your application. This is frequently an issue that prevents some processes from operating. However, this does not necessarily imply that the application has been affected. The code should, in fact, continue to function normally. If the issue recurs, you should examine these warnings at some point." [& message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :warn)] + (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy *ns* :warn)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log ~logger-id# :warn ~@message) `(automaton-core.log.be-log/log ~logger-id# :warn ~@message)))) @@ -139,26 +170,35 @@ (defmacro warn-exception "Like warn, but focused on exceptions." [exception & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :warn)] + (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy *ns* :warn)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-exception ~logger-id# :warn ~exception ~@additional-message) - `(automaton-core.log.be-log/log-exception ~logger-id# :warn ~exception ~@additional-message)))) + `(automaton-core.log.fe-log/log-exception ~logger-id# + :warn + ~exception + ~@additional-message) + `(automaton-core.log.be-log/log-exception ~logger-id# + :warn + ~exception + ~@additional-message)))) (defmacro warn-data "Like warn, but first argument is expected to be a map with usefull more detailed data." [data & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :warn)] + (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy *ns* :warn)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-data ~logger-id# :warn ~data ~@additional-message) - `(automaton-core.log.be-log/log-data ~logger-id# :warn ~data ~@additional-message)))) + `(automaton-core.log.fe-log/log-data ~logger-id# + :warn + ~data + ~@additional-message) + `(automaton-core.log.be-log/log-data ~logger-id# + :warn + ~data + ~@additional-message)))) (defmacro warn-format "Like warn, but uses clojure format function, so first argument is string to translate and rest is arguments to supply it with." [fmt & args] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :warn)] + (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy *ns* :warn)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log-format ~logger-id# :warn ~fmt ~@args) `(automaton-core.log.be-log/log-format ~logger-id# :warn ~fmt ~@args)))) @@ -166,8 +206,8 @@ (defmacro error "This ERROR indicates that something critical in your application has failed. This log level is used when a serious issue is preventing the application's functionalities from functioning properly. The application will continue to run for the most part, but it will need to be handled at some point." [& message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :error)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :error)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log ~logger-id# :error ~@message) `(automaton-core.log.be-log/log ~logger-id# :error ~@message)))) @@ -175,26 +215,38 @@ (defmacro error-exception "Like error, but focused on exceptions." [exception & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :error)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :error)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-exception ~logger-id# :error ~exception ~@additional-message) - `(automaton-core.log.be-log/log-exception ~logger-id# :error ~exception ~@additional-message)))) + `(automaton-core.log.fe-log/log-exception ~logger-id# + :error + ~exception + ~@additional-message) + `(automaton-core.log.be-log/log-exception ~logger-id# + :error + ~exception + ~@additional-message)))) (defmacro error-data "Like error, but first argument is expected to be a map with usefull more detailed data." [data & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :error)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :error)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-data ~logger-id# :error ~data ~@additional-message) - `(automaton-core.log.be-log/log-data ~logger-id# :error ~data ~@additional-message)))) + `(automaton-core.log.fe-log/log-data ~logger-id# + :error + ~data + ~@additional-message) + `(automaton-core.log.be-log/log-data ~logger-id# + :error + ~data + ~@additional-message)))) (defmacro error-format "Like error, but uses clojure format function, so first argument is string to translate and rest is arguments to supply it with." [fmt & args] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :error)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :error)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log-format ~logger-id# :error ~fmt ~@args) `(automaton-core.log.be-log/log-format ~logger-id# :error ~fmt ~@args)))) @@ -202,8 +254,8 @@ (defmacro fatal "FATAL indicates that the application is about to prevent a major problem or corruption. The FATAL level of logging indicates that the application's situation is critical, such as when a critical function fails. If the application is unable to connect to the data store, for example, you can utilise the FATAL log level." [& message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :fatal)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :fatal)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log ~logger-id# :fatal ~@message) `(automaton-core.log.be-log/log ~logger-id# :fatal ~@message)))) @@ -211,26 +263,38 @@ (defmacro fatal-exception "Like fatal, but focused on exceptions." [exception & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :fatal)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :fatal)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-exception ~logger-id# :fatal ~exception ~@additional-message) - `(automaton-core.log.be-log/log-exception ~logger-id# :fatal ~exception ~@additional-message)))) + `(automaton-core.log.fe-log/log-exception ~logger-id# + :fatal + ~exception + ~@additional-message) + `(automaton-core.log.be-log/log-exception ~logger-id# + :fatal + ~exception + ~@additional-message)))) (defmacro fatal-data "Like fatal, but first argument is expected to be a map with usefull more detailed data." [data & additional-message] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :fatal)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :fatal)] (if (cljs-env? &env) - `(automaton-core.log.fe-log/log-data ~logger-id# :fatal ~data ~@additional-message) - `(automaton-core.log.be-log/log-data ~logger-id# :fatal ~data ~@additional-message)))) + `(automaton-core.log.fe-log/log-data ~logger-id# + :fatal + ~data + ~@additional-message) + `(automaton-core.log.be-log/log-data ~logger-id# + :fatal + ~data + ~@additional-message)))) (defmacro fatal-format "Like fatal, but uses clojure format function, so first argument is string to translate and rest is arguments to supply it with." [fmt & args] - (let [logger-id# (automaton-core.log.strategy/apply-strategy stgy - *ns* :fatal)] + (let [logger-id# + (automaton-core.log.strategy/apply-strategy stgy *ns* :fatal)] (if (cljs-env? &env) `(automaton-core.log.fe-log/log-format ~logger-id# :fatal ~fmt ~@args) `(automaton-core.log.be-log/log-format ~logger-id# :fatal ~fmt ~@args)))) diff --git a/src/cljc/automaton_core/log/log_levels.cljc b/src/cljc/automaton_core/log/log_levels.cljc index 3dba3f2a..b8bb126b 100644 --- a/src/cljc/automaton_core/log/log_levels.cljc +++ b/src/cljc/automaton_core/log/log_levels.cljc @@ -3,12 +3,7 @@ (def levels-sequence "List error levels in our app, first is more detailed, last is least detailed" - {:trace 10 - :debug 20 - :info 30 - :warn 40 - :error 50 - :fatal 60}) + {:trace 10, :debug 20, :info 30, :warn 40, :error 50, :fatal 60}) (defn execute-level? "Returns true if we decide to apply log to that levl regarding minimimum required @@ -16,7 +11,5 @@ * `min-level-kw` - keyword of the minimum log level expected * `level-kw` - keyword of the log to test" [min-level-kw level-kw] - (when (and level-kw min-level-kw) - (apply <= - (map (partial get levels-sequence) - [min-level-kw level-kw])))) + (when (and level-kw min-level-kw) + (apply <= (map (partial get levels-sequence) [min-level-kw level-kw])))) diff --git a/src/cljc/automaton_core/log/registry.cljc b/src/cljc/automaton_core/log/registry.cljc index 603e56b0..82007b5a 100644 --- a/src/cljc/automaton_core/log/registry.cljc +++ b/src/cljc/automaton_core/log/registry.cljc @@ -1,10 +1,12 @@ -(ns automaton-core.log.registry - "List all known strategies") +(ns automaton-core.log.registry "List all known strategies") (def strategies-registry "List of predefined strategies Look at be-registry and fe-registry for implementations." - {::print {:description "Simple print"} - ::text-based {:description "Basic one - sends everything to flatten text (js/console for clojurescript and log4j2 for clojure)"} - ::no-op {:description "Deactivate that log"} - ::error-tracking {:description "Strategy for exception monitoring logging type"}}) + {::print {:description "Simple print"}, + ::text-based + {:description + "Basic one - sends everything to flatten text (js/console for clojurescript and log4j2 for clojure)"}, + ::no-op {:description "Deactivate that log"}, + ::error-tracking {:description + "Strategy for exception monitoring logging type"}}) diff --git a/src/cljc/automaton_core/log/strategy.cljc b/src/cljc/automaton_core/log/strategy.cljc index 8bc6e9ad..da8fd86a 100644 --- a/src/cljc/automaton_core/log/strategy.cljc +++ b/src/cljc/automaton_core/log/strategy.cljc @@ -2,5 +2,7 @@ "Strategy to choose what logger is used where and when") (defprotocol Strategy - (apply-strategy [this ns level] "Return the seq of ids of the chosen rule according to that strategy") - (rule-ids [this] "List of known rule ids in that strategy, adding the `no-op` strategy defaulting your parameters")) + (apply-strategy [this ns level] + "Return the seq of ids of the chosen rule according to that strategy") + (rule-ids [this] + "List of known rule ids in that strategy, adding the `no-op` strategy defaulting your parameters")) diff --git a/src/cljc/automaton_core/log/strategy/static_ns_level.cljc b/src/cljc/automaton_core/log/strategy/static_ns_level.cljc index 4c319605..c4f9327a 100644 --- a/src/cljc/automaton_core/log/strategy/static_ns_level.cljc +++ b/src/cljc/automaton_core/log/strategy/static_ns_level.cljc @@ -7,10 +7,9 @@ * All selected lines could then decide on runtime if there are needed or not. For instance log4j2 logger could use its own parameters to update dynamically which one is used or not See `automaton-core.log.strategy.static-ns-level/ns-rules` for rule definition details " - (:require - [automaton-core.log.log-levels :as log-levels] - [automaton-core.log.strategy :as log-strategy] - [automaton-core.log.registry :as log-registry])) + (:require [automaton-core.log.log-levels :as log-levels] + [automaton-core.log.strategy :as log-strategy] + [automaton-core.log.registry :as log-registry])) (def ns-rules "Decides the level of log depending on namespace @@ -22,44 +21,41 @@ * `re` - is the regular expression to apply on the namespace to decide if the rule apply or not * `min-level` - is the minimum expected log level to be printed (so all greater or equal log levels are printed). Not providing that value means all levels accepted * `:logger` - seq of loggers ids to apply, loggers themselves are defined later on, in clj and cljs sides as their implementation depends on the technology most of the time" - [{:rule-id :rule2 :re #"automaton-core.log" :min-level :debug :logger [::log-registry/print]} - {:rule-id :rule1 :re #"automaton-core.*" :min-level :info :logger [::log-registry/print]}]) + [{:rule-id :rule2, + :re #"automaton-core.log", + :min-level :debug, + :logger [::log-registry/print]} + {:rule-id :rule1, + :re #"automaton-core.*", + :min-level :info, + :logger [::log-registry/print]}]) (defn apply-ns-rule "If `ns` match the regular expression `re` then return a vector with: * the minimum level required to display that message * a description of the rule as a second parameter (useful for tracing the decision if log are needed)" - [ns {:keys [re] :as rule}] - (when re - (when (re-find re (str ns)) - rule))) + [ns {:keys [re], :as rule}] + (when re (when (re-find re (str ns)) rule))) -(defrecord StaticNsLevelStrategy - [ns-rules] +(defrecord StaticNsLevelStrategy [ns-rules] log-strategy/Strategy - (apply-strategy [_ ns level] - (let [active-rule (some-> (keep (partial apply-ns-rule ns) - ns-rules) - first)] - (if (some-> active-rule - :min-level - (log-levels/execute-level? level)) - (:logger active-rule) - [::log-registry/text-based - ::log-registry/error-tracking]))) - - (rule-ids [_] - (set (cons ::log-registry/no-op - (reduce (fn [acc rule] - (concat acc (:logger rule))) - [] - ns-rules))))) + (apply-strategy [_ ns level] + (let [active-rule (some-> (keep (partial apply-ns-rule ns) ns-rules) + first)] + (if (some-> active-rule + :min-level + (log-levels/execute-level? level)) + (:logger active-rule) + [::log-registry/text-based ::log-registry/error-tracking]))) + (rule-ids [_] + (set (cons ::log-registry/no-op + (reduce (fn [acc rule] (concat acc (:logger rule))) + [] + ns-rules))))) (defn make-static-ns-level-strategy "Build the `log-strategy/Strategy` instance applying the static ns level rule Params: * `ns-rules` set of rules to feed the chooser" - ([ns-rules*] - (->StaticNsLevelStrategy ns-rules*)) - ([] - (make-static-ns-level-strategy ns-rules))) + ([ns-rules*] (->StaticNsLevelStrategy ns-rules*)) + ([] (make-static-ns-level-strategy ns-rules))) diff --git a/src/cljc/automaton_core/log/tracking/sentry.cljc b/src/cljc/automaton_core/log/tracking/sentry.cljc index 22ed49fe..3d797769 100644 --- a/src/cljc/automaton_core/log/tracking/sentry.cljc +++ b/src/cljc/automaton_core/log/tracking/sentry.cljc @@ -1,11 +1,11 @@ -(ns automaton-core.log.tracking.sentry - "Sentry shareable code") +(ns automaton-core.log.tracking.sentry "Sentry shareable code") -(defn event-environment [event] +(defn event-environment + [event] #?(:clj (. event getEnvironment) :cljs event.environment)) -(defn silence-development-events [event] +(defn silence-development-events + [event] (let [environment (event-environment event)] - (when-not (= environment "development") - event))) + (when-not (= environment "development") event))) diff --git a/src/cljc/automaton_core/url.cljc b/src/cljc/automaton_core/url.cljc index e16d03fb..d08c01f7 100644 --- a/src/cljc/automaton_core/url.cljc +++ b/src/cljc/automaton_core/url.cljc @@ -2,21 +2,15 @@ "Url management See [lambdaisland.uri](https://cljdoc.org/d/lambdaisland/uri/1.15.125/doc/readme) for useful functions And see the [RFC](https://www.ietf.org/rfc/rfc3986.txt) for references" - (:require - [lambdaisland.uri :as lambda-uri])) + (:require [lambdaisland.uri :as lambda-uri])) (comment - (into {} - (lambda-uri/uri "http://www.hephaistox.com/foo'bar?lang=fr")) + (into {} (lambda-uri/uri "http://www.hephaistox.com/foo'bar?lang=fr")) ;{:scheme "http", - ; :user nil, - ; :password nil, - ; :host "www.hephaistox.com", - ; :port nil, - ; :path "/foo'bar", - ; :query "lang=fr", + ; :user nil, :password nil, :host "www.hephaistox.com", :port nil, :path + ; "/foo'bar", :query "lang=fr", ; :fragment nil} - ) +) (defn extract-tld-from-host "Extract the tld from an host @@ -32,20 +26,15 @@ "According to [RFC3986 page 12](https://www.ietf.org/rfc/rfc3986.txt): gen-delims = : / ? # [ ] @ sub-delims = ! $ & ' ( ) * + , ; =" - {:gen-delims [":" "/" "?" "#" "[" "]" "@"] - :sub-delims ["!" "$" "&" "'" "(" ")" - "*" "+" "," ";" "="]}) + {:gen-delims [":" "/" "?" "#" "[" "]" "@"], + :sub-delims ["!" "$" "&" "'" "(" ")" "*" "+" "," ";" "="]}) (defn compare-locations "Is the url given as a parameter the current location? Params: * `urls` - sequence of url you want to compare" [& urls] - (apply = - (map (comp (juxt :path - :query) - lambda-uri/uri) - urls))) + (apply = (map (comp (juxt :path :query) lambda-uri/uri) urls))) (defn parse-queries "Parse queries to get the parameters diff --git a/src/cljc/automaton_core/utils/fallback.cljc b/src/cljc/automaton_core/utils/fallback.cljc index fd48837f..44988bd0 100644 --- a/src/cljc/automaton_core/utils/fallback.cljc +++ b/src/cljc/automaton_core/utils/fallback.cljc @@ -1,7 +1,6 @@ (ns automaton-core.utils.fallback "Fallback utilties" - (:require - [automaton-core.log :as log]) + (:require [automaton-core.log :as log]) #?(:cljs (:require-macros [automaton-core.utils.fallback]))) (defn cljs-env? @@ -19,12 +18,10 @@ #?(:clj Throwable :cljs :default)) ns (str *ns*)] - `(try - (~expr-fn) - (catch ~catch-level# e# - (log/error-exception (ex-info "Failed but defaulted to ret-val" - {:error e# - :data {:ret-val ~ret-val - :expr-fn ~expr-fn - :ns ~ns}})) - ~ret-val)))) + `(try (~expr-fn) + (catch ~catch-level# e# + (log/error-exception + (ex-info "Failed but defaulted to ret-val" + {:error e#, + :data {:ret-val ~ret-val, :expr-fn ~expr-fn, :ns ~ns}})) + ~ret-val)))) diff --git a/src/cljc/automaton_core/utils/map.cljc b/src/cljc/automaton_core/utils/map.cljc index c424fe3e..30c714ae 100644 --- a/src/cljc/automaton_core/utils/map.cljc +++ b/src/cljc/automaton_core/utils/map.cljc @@ -6,18 +6,13 @@ (defn idx-of "Return the index of the first found value in the sequence" [v value] - (ffirst - (filter #(= value (second %)) - (map-indexed vector v)))) + (ffirst (filter #(= value (second %)) (map-indexed vector v)))) (defn idx-of-pred "Same as idx-of but with a predicate" [v pred] - (when (and pred - (fn? pred)) - (ffirst - (filter #(pred (second %)) - (map-indexed vector v))))) + (when (and pred (fn? pred)) + (ffirst (filter #(pred (second %)) (map-indexed vector v))))) (defn deep-merge "Deep merge nested maps. @@ -25,67 +20,57 @@ This code comes from this [gist](https://gist.github.com/danielpcox/c70a8aa2c36766200a95)" [& maps] - (apply merge-with (fn [& args] - (if (every? #(or (map? %) (nil? %)) args) - (apply deep-merge args) - (last args))) - maps)) + (apply merge-with + (fn [& args] + (if (every? #(or (map? %) (nil? %)) args) + (apply deep-merge args) + (last args))) + maps)) -(defn prefixify-map [prefix thing] +(defn prefixify-map + [prefix thing] (if (map? thing) (set/rename-keys - thing - (->> (keys thing) - (map (fn [k] - [k - (keyword (str (name prefix) "." (name k)))])) - (into {}))) + thing + (->> (keys thing) + (map (fn [k] [k (keyword (str (name prefix) "." (name k)))])) + (into {}))) thing)) -(defn prefixify-vec [prefix thing] +(defn prefixify-vec + [prefix thing] (let [rename (fn [el] (if (map? el) - (seq - (set/rename-keys - el - (->> (keys el) - (map (fn [k] - [k - (keyword (str (name prefix) "." (name k)))])) - (into {})))) + (seq (set/rename-keys el + (->> (keys el) + (map (fn [k] [k + (keyword + (str (name prefix) + "." + (name k)))])) + (into {})))) el))] (if (vector? thing) (let [maps (filter map? thing) non-maps (remove map? thing)] - (merge - (->> (map rename maps) - (apply concat) - (group-by key) - (map (fn [[k vs]] - {k (map second vs)})) - (into {})) - (when (seq non-maps) - {prefix non-maps}))) + (merge (->> (map rename maps) + (apply concat) + (group-by key) + (map (fn [[k vs]] {k (map second vs)})) + (into {})) + (when (seq non-maps) {prefix non-maps}))) thing))) -(defn prefixify-children [thing] +(defn prefixify-children + [thing] (if (map? thing) (->> thing (map (fn [[k v]] - (cond (map? v) - (let [prefixed (prefixify-map k v)] - (if (map? prefixed) - prefixed - {k v})) - - (vector? v) - (let [prefixed (prefixify-vec k v)] - (if (map? prefixed) - prefixed - {k v})) - - :else - {k v}))) + (cond (map? v) (let [prefixed (prefixify-map k v)] + (if (map? prefixed) prefixed {k v})) + (vector? v) (let [prefixed (prefixify-vec k v)] + (if (map? prefixed) prefixed {k v})) + :else {k v}))) (apply merge)) thing)) @@ -95,9 +80,7 @@ (when (map? m) (->> (walk/postwalk prefixify-children m) (map (fn [[k v]] - {k (if (sequential? v) - (flatten v) - v)})) + {k (if (sequential? v) (flatten v) v)})) (into {})))) (defn add-ids @@ -110,20 +93,15 @@ (let [language (cond-> language (map? language) (assoc :id lang-id))] [lang-id language])) - m))) + m))) (defn update-kw "Update the keywords `kws` in map `m` with function `f`" [m kws f] (reduce (fn [m k] - (if (contains? m k) - (let [v (get m k)] - (assoc m - k - (f v))) - m)) - m - kws)) + (if (contains? m k) (let [v (get m k)] (assoc m k (f v))) m)) + m + kws)) (defn apply-to-keys "Apply function `f` to each key in `ks` in the maps in `maps` @@ -132,13 +110,7 @@ * `maps` is a sequence of map * `ks` keys in the map to apply `f` to" [maps f & ks] - (mapv (fn [m] - (reduce (fn [m k] - (assoc m - k (f m k (get m k)))) - m - ks)) - maps)) + (mapv (fn [m] (reduce (fn [m k] (assoc m k (f m k (get m k)))) m ks)) maps)) (defn map-util-hashmappify-vals "Converts an ordinary Clojure map into a Clojure map with nested map diff --git a/src/cljc/automaton_core/utils/sequences.cljc b/src/cljc/automaton_core/utils/sequences.cljc index 6b7f0160..4e13c412 100644 --- a/src/cljc/automaton_core/utils/sequences.cljc +++ b/src/cljc/automaton_core/utils/sequences.cljc @@ -1,5 +1,4 @@ -(ns automaton-core.utils.sequences - "Manipulation of sequences") +(ns automaton-core.utils.sequences "Manipulation of sequences") (defn trim-leading-nil "Remove nil values at the end of a sequence @@ -8,13 +7,9 @@ * `nil-fn` is the function to test nullity, (defaulted to `nil?`)" ([aseq nil-fn] (loop [aseq aseq - i 40] ;; For security reason - (when-not (pos? i) - (throw (ex-info "Infinite loop detected" {}))) - (if (and (seq aseq) - (nil-fn (last aseq))) - (recur (butlast aseq) - (dec i)) + i 40] ;; For security reason + (when-not (pos? i) (throw (ex-info "Infinite loop detected" {}))) + (if (and (seq aseq) (nil-fn (last aseq))) + (recur (butlast aseq) (dec i)) aseq))) - ([aseq] - (trim-leading-nil aseq nil?))) + ([aseq] (trim-leading-nil aseq nil?))) diff --git a/src/cljc/automaton_core/utils/string_to_id.cljc b/src/cljc/automaton_core/utils/string_to_id.cljc index 45c317dc..e61f41eb 100644 --- a/src/cljc/automaton_core/utils/string_to_id.cljc +++ b/src/cljc/automaton_core/utils/string_to_id.cljc @@ -1,9 +1,8 @@ (ns automaton-core.utils.string-to-id "Transform a string into an id That id are currently used and tested for React" - (:require - [clojure.string :as str] - [automaton-core.utils.uuid-gen :as uuid])) + (:require [clojure.string :as str] + [automaton-core.utils.uuid-gen :as uuid])) (defn string-to-id "Transform what is not alphanumerical to an id diff --git a/src/cljc/automaton_core/utils/uuid_gen.cljc b/src/cljc/automaton_core/utils/uuid_gen.cljc index 42ccd268..634b0e20 100644 --- a/src/cljc/automaton_core/utils/uuid_gen.cljc +++ b/src/cljc/automaton_core/utils/uuid_gen.cljc @@ -1,14 +1,12 @@ (ns automaton-core.utils.uuid-gen "Generate uuid, is a proxy to `http://danlentz.github.io/clj-uuid/`" - (:require - #?(:clj [clj-uuid :as uuid]))) + (:require #?(:clj [clj-uuid :as uuid]))) (defn time-based-uuid "Generate a time based uuid, so sorting uuid is sorting chronologically" [] #?(:clj (uuid/v1) - :cljs (throw (ex-info "Not implemented yet" - {})))) + :cljs (throw (ex-info "Not implemented yet" {})))) (defn unguessable "When the uuid should not be guessed" diff --git a/src/cljs/automaton_core/log/fe_log.cljc b/src/cljs/automaton_core/log/fe_log.cljc index 39a0f517..ce51809a 100644 --- a/src/cljs/automaton_core/log/fe_log.cljc +++ b/src/cljs/automaton_core/log/fe_log.cljc @@ -1,49 +1,50 @@ (ns automaton-core.log.fe-log "Factory generating log function" - (:require - [automaton-core.log.strategy] - [automaton-core.log.fe-registry] - [automaton-core.log.strategy.static-ns-level] - #?(:cljs [automaton-core.log.tracking.fe-error-tracking :as exs])) - #?(:cljs (:require-macros - [automaton-core.log.fe-log]))) + (:require [automaton-core.log.strategy] + [automaton-core.log.fe-registry] + [automaton-core.log.strategy.static-ns-level] + #?(:cljs [automaton-core.log.tracking.fe-error-tracking :as exs])) + #?(:cljs (:require-macros [automaton-core.log.fe-log]))) -#?(:cljs (defn log-init! [params] - (exs/init-error-tracking! params))) +#?(:cljs (defn log-init! [params] (exs/init-error-tracking! params))) (defn logger-ids-to-logger-fns [logger-ids] (reduce (fn [acc logger-id] - (conj acc (get-in #?(:cljs automaton-core.log.fe-registry/strategies-registry - :clj {}) - [logger-id :impl]))) - [] - logger-ids)) + (conj acc + (get-in + #?(:cljs automaton-core.log.fe-registry/strategies-registry + :clj {}) + [logger-id :impl]))) + [] + logger-ids)) (defmacro log [logger-id level & message] (let [ns (str *ns*) - log-fns `(automaton-core.log.fe-log/logger-ids-to-logger-fns ~logger-id)] + log-fns `(automaton-core.log.fe-log/logger-ids-to-logger-fns + ~logger-id)] `((apply juxt ~log-fns) ~ns (str ~level) ~@message))) (defmacro log-exception [logger-id level exception & additional-message] - (when additional-message - (log logger-id level additional-message)) + (when additional-message (log logger-id level additional-message)) (let [ns (str *ns*) - log-fns `(automaton-core.log.fe-log/logger-ids-to-logger-fns ~logger-id)] + log-fns `(automaton-core.log.fe-log/logger-ids-to-logger-fns + ~logger-id)] `((apply juxt ~log-fns) ~ns (str ~level) ~exception))) (defmacro log-data [logger-id level data & additional-message] - (when additional-message - (log logger-id additional-message)) + (when additional-message (log logger-id additional-message)) (let [ns (str *ns*) - log-fns `(automaton-core.log.fe-log/logger-ids-to-logger-fns ~logger-id)] + log-fns `(automaton-core.log.fe-log/logger-ids-to-logger-fns + ~logger-id)] `((apply juxt ~log-fns) ~ns (str ~level) ~data))) (defmacro log-format [logger-id level fmt & data] (let [ns (str *ns*) - log-fns `(automaton-core.log.fe-log/logger-ids-to-logger-fns ~logger-id)] + log-fns `(automaton-core.log.fe-log/logger-ids-to-logger-fns + ~logger-id)] `((apply juxt ~log-fns) ~ns (str ~level) (format ~fmt ~@data)))) diff --git a/src/cljs/automaton_core/log/fe_registry.cljc b/src/cljs/automaton_core/log/fe_registry.cljc index ada1866d..8721d716 100644 --- a/src/cljs/automaton_core/log/fe_registry.cljc +++ b/src/cljs/automaton_core/log/fe_registry.cljc @@ -1,28 +1,23 @@ (ns automaton-core.log.fe-registry "List of all known frontend strategies" - (:require - [automaton-core.log.registry :as log-registry] - #?@(:cljs [[automaton-core.log.impl.print] - [automaton-core.log.tracking.fe-error-tracking]]))) + (:require [automaton-core.log.registry :as log-registry] + #?@(:cljs [[automaton-core.log.impl.print] + [automaton-core.log.tracking.fe-error-tracking]]))) -(defn no-op-fn [& _] - nil) +(defn no-op-fn [& _] nil) -(defn simple-print - [_ns _level & msg] - (apply print msg)) +(defn simple-print [_ns _level & msg] (apply print msg)) (def strategies-registry "List of predefined strategies Look at clj and cljs implementations to have an understanding of that strategies implementation which may be different on both technologies. For instance, `:text-based` will be based on log4j2 on backedn and console on frontend" - {::log-registry/print {:description "Simple print" - :impl simple-print} - ::log-registry/text-based {:description "Basic one - sends everything to flatten text (js/console for clojurescript and log4j2 for clojure)" - #?@(:cljs - [:impl automaton-core.log.impl.print/log-fn])} - ::log-registry/no-op {:description "Deactivate that log" - :impl no-op-fn} - ::log-registry/error-tracking {:description "For monitoring exceptions in the application" - #?@(:cljs - [:impl automaton-core.log.tracking.fe-error-tracking/log-fn])}}) + {::log-registry/print {:description "Simple print", :impl simple-print}, + ::log-registry/text-based + {:description + "Basic one - sends everything to flatten text (js/console for clojurescript and log4j2 for clojure)", + #?@(:cljs [:impl automaton-core.log.impl.print/log-fn])}, + ::log-registry/no-op {:description "Deactivate that log", :impl no-op-fn}, + ::log-registry/error-tracking + {:description "For monitoring exceptions in the application", + #?@(:cljs [:impl automaton-core.log.tracking.fe-error-tracking/log-fn])}}) diff --git a/src/cljs/automaton_core/log/impl/print.cljs b/src/cljs/automaton_core/log/impl/print.cljs index d19bd059..8c8f29de 100644 --- a/src/cljs/automaton_core/log/impl/print.cljs +++ b/src/cljs/automaton_core/log/impl/print.cljs @@ -1,8 +1,7 @@ (ns automaton-core.log.impl.print "Simple print namespace, most likely used just temporarily. trace -> debug -> info -> warn -> error -> fatal" - (:require - [clojure.string :as str])) + (:require [clojure.string :as str])) (defn get-logger "The logger version for js console is based in the order found in that [article](https://www.atatus.com/blog/javascript-logging-basic-tips/) @@ -26,5 +25,4 @@ trace -> debug -> info -> warn -> error -> fatal" * `message` " [_ level & message] - (let [logger (get-logger level)] - (logger (str/join " " message)))) + (let [logger (get-logger level)] (logger (str/join " " message)))) diff --git a/src/cljs/automaton_core/log/print.cljs b/src/cljs/automaton_core/log/print.cljs index 58b84bf1..c3946622 100644 --- a/src/cljs/automaton_core/log/print.cljs +++ b/src/cljs/automaton_core/log/print.cljs @@ -1,8 +1,7 @@ (ns automaton-core.log.print "Simple print namespace, most likely used just temporarily. trace -> debug -> info -> warn -> error -> fatal" - (:require - [clojure.string :as str])) + (:require [clojure.string :as str])) (defn get-logger "The logger version for js console is based in the order found in that [article](https://www.atatus.com/blog/javascript-logging-basic-tips/) @@ -26,5 +25,4 @@ trace -> debug -> info -> warn -> error -> fatal" * `message` " [_ level & message] - (let [logger (get-logger level)] - (logger (str/join " " message)))) + (let [logger (get-logger level)] (logger (str/join " " message)))) diff --git a/src/cljs/automaton_core/log/tracking/fe_error_tracking.cljs b/src/cljs/automaton_core/log/tracking/fe_error_tracking.cljs index 61085874..b317ae96 100644 --- a/src/cljs/automaton_core/log/tracking/fe_error_tracking.cljs +++ b/src/cljs/automaton_core/log/tracking/fe_error_tracking.cljs @@ -4,24 +4,14 @@ (defn init-error-tracking! [{:keys [dsn env traced-website]}] - (sentry/init-sentry! - {:dsn dsn - :traced-website traced-website - :env env})) + (sentry/init-sentry! {:dsn dsn, :traced-website traced-website, :env env})) -(defn log-fn [ns level & message] - (let [context (if (map? (first message)) - (merge (first message) - {:ns ns}) - {:ns ns}) - message (if (map? (first message)) - (rest message) - message)] - (if (or (= level :error) - (= level :fatal)) - (sentry/send-event! {:message message - :level level - :context context}) - (sentry/send-breadcrumb! {:message message - :level level - :context context})))) +(defn log-fn + [ns level & message] + (let [context + (if (map? (first message)) (merge (first message) {:ns ns}) {:ns ns}) + message (if (map? (first message)) (rest message) message)] + (if (or (= level :error) (= level :fatal)) + (sentry/send-event! {:message message, :level level, :context context}) + (sentry/send-breadcrumb! + {:message message, :level level, :context context})))) diff --git a/src/cljs/automaton_core/log/tracking/fe_sentry.cljs b/src/cljs/automaton_core/log/tracking/fe_sentry.cljs index 5027b589..6aa9dc67 100644 --- a/src/cljs/automaton_core/log/tracking/fe_sentry.cljs +++ b/src/cljs/automaton_core/log/tracking/fe_sentry.cljs @@ -1,50 +1,43 @@ (ns automaton-core.log.tracking.fe-sentry "Sentry frontend logging." - (:require [react :as react] - ["@sentry/react" :as Sentry] - ["react-router-dom" :refer (useLocation useNavigationType - createRoutesFromChildren - matchRoutes)] - [automaton-core.log.tracking.sentry :as asentry])) + (:require + [react :as react] + ["@sentry/react" :as Sentry] + ["react-router-dom" :refer + (useLocation useNavigationType createRoutesFromChildren matchRoutes)] + [automaton-core.log.tracking.sentry :as asentry])) (defn send-breadcrumb! "Sends breadcrumb, which will not be shown in sentry untill event is sent. You can read more here: https://docs.sentry.io/platforms/javascript/guides/react/enriching-events/breadcrumbs/" [{:keys [message level context]}] - (.addBreadcrumb Sentry (clj->js {:level level - :message message - :data context}))) + (.addBreadcrumb Sentry + (clj->js {:level level, :message message, :data context}))) (defn send-event! "Sends an event that is registered in sentry." [{:keys [message level context]}] - (.captureEvent Sentry (clj->js {:level level - :message message - :extra context}))) + (.captureEvent Sentry + (clj->js {:level level, :message message, :extra context}))) (defn init-sentry! "Initialize sentry for react, which is recording react errors that happens inside the components and enables to send events. 'development' as an environment is ignored, so no event is sent from it." [{:keys [dsn traced-website env]}] (.init Sentry - #js - {:dsn dsn - :environment env - :integrations - #js - [(new - (.-BrowserTracing Sentry) - #js - {:routingInstrumentation - (.reactRouterV6Instrumentation - Sentry - react/useEffect - useLocation - useNavigationType - createRoutesFromChildren - matchRoutes)}) (new (.-Replay Sentry))], - :tracesSampleRate 1.0 - :tracePropagationTargets #js ["localhost" - traced-website] - :beforeSend (fn [event] - (asentry/silence-development-events event))})) + #js {:dsn dsn, + :environment env, + :integrations #js [(new (.-BrowserTracing Sentry) + #js {:routingInstrumentation + (.reactRouterV6Instrumentation + Sentry + react/useEffect + useLocation + useNavigationType + createRoutesFromChildren + matchRoutes)}) + (new (.-Replay Sentry))], + :tracesSampleRate 1.0, + :tracePropagationTargets #js ["localhost" traced-website], + :beforeSend (fn [event] + (asentry/silence-development-events event))})) diff --git a/test/clj/automaton_core/adapters/bb_edn_test.clj b/test/clj/automaton_core/adapters/bb_edn_test.clj deleted file mode 100644 index bc530d04..00000000 --- a/test/clj/automaton_core/adapters/bb_edn_test.clj +++ /dev/null @@ -1,39 +0,0 @@ -(ns automaton-core.adapters.bb-edn-test - (:require - [clojure.test :refer [deftest is testing]] - - [automaton-core.adapters.bb-edn :as sut] - [automaton-core.adapters.files :as files])) - -(deftest update-bb-edn-test - (testing "Update edn keep `:init` and `:requires` keys, and add what is in tasks" - (let [tmp-bb-dir (files/create-temp-dir) - update-fn (fn [bb-edn] - (assoc bb-edn - :new-tasks - {"foo4" {:cli-params-mode :none - :doc "Test" - :exec-task 'bar} - "foo2" {:cli-params-mode :none - :doc "Test2" - :exec-task 'bar2}}))] - - (files/spit-file (files/create-file-path tmp-bb-dir sut/bb-edn-filename) - {:paths [] - :deps {} - :tasks {:init "don't touch" - :requires "neither"}}) - (is (= {:paths [], - :deps {}, - :tasks - {:init "don't touch", - :requires "neither"} - :new-tasks {"foo4" {:cli-params-mode :none - :doc "Test" - :exec-task 'bar} - "foo2" {:cli-params-mode :none - :doc "Test2" - :exec-task 'bar2}}} - - (sut/update-bb-edn tmp-bb-dir - update-fn)))))) diff --git a/test/clj/automaton_core/adapters/build_config_test.clj b/test/clj/automaton_core/adapters/build_config_test.clj index e5923b08..3b1c86fb 100644 --- a/test/clj/automaton_core/adapters/build_config_test.clj +++ b/test/clj/automaton_core/adapters/build_config_test.clj @@ -11,6 +11,11 @@ (is (> (count (sut/search-for-build-config)) 0)))) +(def tmp-dir (files/create-temp-dir)) + +(def content + {:foo3 :bar3}) + (deftest spit-build-config-test (testing "Check spitted build config is found" (let [tmp-dir (files/create-temp-dir) diff --git a/test/clj/automaton_core/adapters/code_files_test.clj b/test/clj/automaton_core/adapters/code_files_test.clj deleted file mode 100644 index 13f24fc2..00000000 --- a/test/clj/automaton_core/adapters/code_files_test.clj +++ /dev/null @@ -1,73 +0,0 @@ -(ns automaton-core.adapters.code-files-test - (:require - [clojure.test :refer [deftest is testing]] - [automaton-core.adapters.code-files :as sut])) - -(def files-repo {"foo.clj" ["This is" - " the foo file" - " hey!"] - "foo.edn" ["test"] - "bar.cljc" ["This is the bar file" - " ho ho!"]}) -(deftest files-repo-test - (testing "Check files-repo returns filename and content" - (is (sut/validate files-repo)))) - -(deftest code-files-repo-test - (testing "The generated code files repo is compliant with the schema" - (is (sut/validate (sut/code-files-repo ""))))) - -(deftest get-clj*-files-test - (testing "Check the filtering is ok" - (is (= (select-keys files-repo - ["foo.clj" "bar.cljc"]) - (sut/get-clj*-files files-repo))))) - -(deftest exclude-files-test - (testing "Exclude none file" - (is (= files-repo - (sut/exclude-files files-repo - #{"none"})))) - (testing "Exlude all files" - (is (= {} - (sut/exclude-files files-repo - #{"foo.clj" "bar.cljc" "foo.edn"}))))) - -(deftest create-report-test - (testing "Check report is well formed" - (is (= [["foo.clj" "is"] - ["bar.cljc" "is"]] - (sut/create-report files-repo - #"is")))) - (testing "Check grouped regexp" - (is (= [["foo.clj" ["is" "is"]] - ["bar.cljc" ["is" "is"]]] - (sut/create-report files-repo - #"(is)")))) - (testing "Gather the whole line" - (is (= [["foo.clj" ["This is" "is"]] - ["bar.cljc" ["This is the bar file" "is"]]] - (sut/create-report files-repo - #".*(is).*")))) - (testing "Check report allow empty results" - (is (empty? - (sut/create-report files-repo - #"ThisIsNotInTheRepo"))))) - -(deftest map-report-test - (let [report (sut/create-report files-repo - #"(is)")] - (is (= [["foo.clj" "is" "is"] - ["bar.cljc" "is" "is"]] - (sut/map-report report - (fn [filename [whole-match match1]] - [filename whole-match match1])))))) - -(deftest print-report-test - (testing "Test the report is ok" - (is (= "The liner is [\"foo.clj\" [\"is\" \"is\"]] !!\nThe liner is [\"bar.cljc\" [\"is\" \"is\"]] !!\n" - (with-out-str - (sut/print-report (sut/create-report files-repo - #"(is)") - (fn [line] - (println (format "The liner is %s !!" line))))))))) diff --git a/test/clj/automaton_core/adapters/code_formatter_test.clj b/test/clj/automaton_core/adapters/code_formatter_test.clj deleted file mode 100644 index 5e0e2260..00000000 --- a/test/clj/automaton_core/adapters/code_formatter_test.clj +++ /dev/null @@ -1,18 +0,0 @@ -(ns automaton-core.adapters.code-formatter-test - (:require - [automaton-core.adapters.code-formatter :as sut] - [clojure.test :refer [deftest is testing]])) - -(deftest format-content-test - (testing "Simple test" - (is (= "{:a :b}" - (sut/format-content {:a :b}))) - (is (= "(do {:a {:b :c}} 1)" - (sut/format-content '(do {:a {:b :c}} 1)))))) - -(comment - ;; This test works only if some modifications are done in the bb.edn or in the task - ;; Note that it will remove the comment line - (sut/format-file "bb.edn") -; - ) diff --git a/test/cljc/automaton_core/utils/fallback_test.cljc b/test/cljc/automaton_core/utils/fallback_test.cljc index 3a0f8127..9f19d383 100644 --- a/test/cljc/automaton_core/utils/fallback_test.cljc +++ b/test/cljc/automaton_core/utils/fallback_test.cljc @@ -4,12 +4,6 @@ :cljs [cljs.test :refer [deftest is testing] :include-macros true]))) (deftest always-return-test - (testing "ret-val is returned when there is exception" - (is (= (sut/always-return #(throw (ex-info "sututu" {})) 15) - 15))) - #?(:clj (testing "ret-val is returned when there is java error" - (is (= (sut/always-return #(throw (AssertionError. "Wrong input")) 15) - 15)))) (testing "When there is no exception function value is returned." (is (= (sut/always-return (fn [] 34) 15) diff --git a/version.edn b/version.edn new file mode 100644 index 00000000..e55b51e0 --- /dev/null +++ b/version.edn @@ -0,0 +1,3 @@ +;; Last generated version, note a failed push consume a number Tue Oct 24 +;; 19:35:07 CEST 2023 +{:major-version "1.2.%s", :minor-version 0, :version "1.2.0"} \ No newline at end of file