diff --git a/.cljfmt.edn b/.cljfmt.edn new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.cljfmt.edn @@ -0,0 +1 @@ + diff --git a/.gitignore b/.gitignore index 72c4629..2b9c8b3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.log *jar .DS_Store +.calva/ .lein-deps-sum .lein-env .lein-failures @@ -11,8 +12,6 @@ .lein-repl-history .nrepl-port .sass-cache/ -/logs -/log app/dev/css/ app/dev/js/ app/prod/css/ @@ -20,6 +19,8 @@ app/prod/js/ classes/* electron/* lib/* +log/ +logs/ madek-app-darwin-x64/ madek-exporter-darwin-x64/ madek-exporter-linux-x64/ diff --git a/.mux.yml b/.mux.yml index 02cd9dd..e8006d0 100644 --- a/.mux.yml +++ b/.mux.yml @@ -6,9 +6,9 @@ windows: command: > rm -rf target && sleep 5 && - lein do repl + ./bin/lein do repl post_command_send_keys: | - (-main) + (-main "server") 3: name: electron-app command: > @@ -20,16 +20,16 @@ windows: rm -rf \ app/dev/js/front.js \ app/dev/js/out_front.js && - lein trampoline figwheel electron-front-dev + ./bin/lein trampoline figwheel electron-front-dev 6: name: electron-main command: > rm -rf app/dev/js/out_main app/dev/js/main.js && - lein trampoline cljsbuild auto electron-main-dev + ./bin/lein trampoline cljsbuild auto electron-main-dev 7: name: css command: | - lein sass watch + ./bin/lein sass watch 9: name: watch-releases command: | diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..9dcaad5 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,14 @@ +# clojure 1.10.1.769 +clojure 1.9.0.397 +# java zulu-8.76.0.17 +java zulu-11.70.15 +lein 2.9.10 +# ruby 2.6.7 +ruby 3.1.3 +nodejs 14.21.2 +# node js 14 seems to want python 3.10.11 +# python 3.10.11 +# nodejs 12.22.12 +# nodejs 10.24.1 +# nodejs 8.17.0 + diff --git a/FIX.md b/FIX.md new file mode 100644 index 0000000..7885a0d --- /dev/null +++ b/FIX.md @@ -0,0 +1,3 @@ + +lein run -- cli --token ARG107Z0FE94230T2SYN0T1F36QR6BT2 + diff --git a/Gemfile b/Gemfile index 911281c..3991632 100644 --- a/Gemfile +++ b/Gemfile @@ -2,16 +2,16 @@ source 'https://rubygems.org' gem 'activesupport' gem 'addressable' -gem 'capybara' -gem 'chromedriver-helper' +gem 'capybara', '>= 2.13.0', '< 3.0.0' +gem 'chromedriver-helper', '>= 1.1.0', '< 2.0.0' gem 'faker' gem 'faraday' gem 'faraday_middleware' gem 'filewatcher' gem 'git' gem 'json_roa-client', '>= 1.0.0', '< 2.0.0' -gem 'poltergeist' +# gem 'poltergeist' gem 'pry' gem 'rest-client' gem 'rspec' -gem 'selenium-webdriver' +gem 'selenium-webdriver', '>= 3.4.0', '< 4.0.0' diff --git a/Gemfile.lock b/Gemfile.lock index 1b5aa3d..fb3dc27 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,109 +1,109 @@ GEM remote: https://rubygems.org/ specs: - activesupport (5.0.2) + activesupport (7.1.3.2) + base64 + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (~> 0.7) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.5.1) - public_suffix (~> 2.0, >= 2.0.2) - archive-zip (0.7.0) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + archive-zip (0.12.0) io-like (~> 0.3.0) - capybara (2.13.0) + base64 (0.2.0) + bigdecimal (3.1.7) + capybara (2.18.0) addressable - mime-types (>= 1.16) + mini_mime (>= 0.1.3) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) - xpath (~> 2.0) - childprocess (0.6.3) - ffi (~> 1.0, >= 1.0.11) - chromedriver-helper (1.1.0) - archive-zip (~> 0.7.0) - nokogiri (~> 1.6) - cliver (0.3.2) - coderay (1.1.1) - concurrent-ruby (1.0.5) - diff-lcs (1.3) - domain_name (0.5.20170404) - unf (>= 0.0.5, < 1.0.0) - faker (1.7.3) - i18n (~> 0.5) - faraday (0.12.1) + xpath (>= 2.0, < 4.0) + childprocess (3.0.0) + chromedriver-helper (1.2.0) + archive-zip (~> 0.10) + nokogiri (~> 1.8) + coderay (1.1.3) + concurrent-ruby (1.2.3) + connection_pool (2.4.1) + diff-lcs (1.5.1) + domain_name (0.6.20240107) + drb (2.2.1) + faker (3.2.3) + i18n (>= 1.8.11, < 2) + faraday (0.17.6) multipart-post (>= 1.2, < 3) - faraday_middleware (0.11.0.1) + faraday_middleware (0.14.0) faraday (>= 0.7.4, < 1.0) - ffi (1.9.18) - filewatcher (0.5.4) - trollop (~> 2.0) - git (1.3.0) - http-cookie (1.0.3) + filewatcher (2.1.0) + module_methods (~> 0.1.0) + git (1.19.1) + addressable (~> 2.8) + rchardet (~> 1.8) + http-accept (1.7.0) + http-cookie (1.0.5) domain_name (~> 0.5) - i18n (0.8.1) - io-like (0.3.0) + i18n (1.14.4) + concurrent-ruby (~> 1.0) + io-like (0.3.1) json_roa-client (1.0.0) addressable (~> 2) faraday (~> 0.9) faraday_middleware (~> 0.9) - method_source (0.8.2) - mime-types (3.1) + method_source (1.0.0) + mime-types (3.5.2) mime-types-data (~> 3.2015) - mime-types-data (3.2016.0521) - mini_portile2 (2.1.0) - minitest (5.10.1) - multipart-post (2.0.0) + mime-types-data (3.2024.0305) + mini_mime (1.1.5) + mini_portile2 (2.8.5) + minitest (5.22.3) + module_methods (0.1.0) + multipart-post (2.4.0) + mutex_m (0.2.0) netrc (0.11.0) - nokogiri (1.7.1) - mini_portile2 (~> 2.1.0) - poltergeist (1.14.0) - capybara (~> 2.1) - cliver (~> 0.3.1) - websocket-driver (>= 0.2.0) - pry (0.10.4) - coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - public_suffix (2.0.5) - rack (2.0.1) - rack-test (0.6.3) - rack (>= 1.0) - rest-client (2.0.2) + nokogiri (1.16.3) + mini_portile2 (~> 2.8.2) + racc (~> 1.4) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + public_suffix (5.0.4) + racc (1.7.3) + rack (3.0.9.1) + rack-test (2.1.0) + rack (>= 1.3) + rchardet (1.8.0) + rest-client (2.1.0) + http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rspec (3.5.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-core (3.5.4) - rspec-support (~> 3.5.0) - rspec-expectations (3.5.0) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-mocks (3.5.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-support (3.5.0) - rubyzip (1.2.1) - selenium-webdriver (3.4.0) - childprocess (~> 0.5) - rubyzip (~> 1.0) - websocket (~> 1.0) - slop (3.6.0) - thread_safe (0.3.6) - trollop (2.1.2) - tzinfo (1.2.3) - thread_safe (~> 0.1) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.4) - websocket (1.2.4) - websocket-driver (0.6.5) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.2) - xpath (2.0.0) - nokogiri (~> 1.3) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) + rubyzip (2.3.2) + selenium-webdriver (3.142.7) + childprocess (>= 0.5, < 4.0) + rubyzip (>= 1.2.2) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + xpath (3.2.0) + nokogiri (~> 1.8) PLATFORMS ruby @@ -111,19 +111,18 @@ PLATFORMS DEPENDENCIES activesupport addressable - capybara - chromedriver-helper + capybara (>= 2.13.0, < 3.0.0) + chromedriver-helper (>= 1.1.0, < 2.0.0) faker faraday faraday_middleware filewatcher git json_roa-client (>= 1.0.0, < 2.0.0) - poltergeist pry rest-client rspec - selenium-webdriver + selenium-webdriver (>= 3.4.0, < 4.0.0) BUNDLED WITH - 1.14.6 + 2.4.12 diff --git a/README.md b/README.md index 4455a28..5cd8753 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,23 @@ We do this via our CI system, see the file [cider-ci.yml](cider-ci.yml). -## Development +### Requirements -See the files [project.clj](project.clj) and [.mux.yml](.mux.yml). +Debian: + +* task-desktop +* zip, unzip +* libgconf-2-4 +* wine +* libxss1 -### First time preparation -`node` and `npm` must be installed and in the execution PATH. Run +## Development - npm install +See the files [project.clj](project.clj) and [.mux.yml](.mux.yml). -Download Electron for your platform. One way to do it is via grunt +Most dependecies are managed via https://asdf-vm.com/ - ./node_modules/grunt/bin/grunt download-electron ### Development targets @@ -29,27 +33,22 @@ There are the following build targets: 3. Electron front, also known as the "renderer", the code is located in `electron_front/`. 4. Stylesheets compiled from sass. -We build each one "continuously" in its own window when developing. A forth -window holds the electron app. + +The watched dev builds are kind of broken now. Until we update the whole app use prod builds. ### JVM main - rm -rf target - lein repl - # it will open a repl in the main namespace, where we can start the server with - (-main) + ./bin/build-jvm-main-prod + The jvm app can be started with _debug_ and _repl_ options for development ; see cli options. ### Electron main - rm -rf app/dev/js/out_main app/dev/js/main.js - lein cljsbuild auto electron-main-dev - + ./bin/build-electron-main-prod ### Electron front - rm -rf app/dev/js/front.js app/dev/js/out_front.js - lein descjop-figwheel + ./bin/build-electron-front-prod ### Stylesheets @@ -59,20 +58,8 @@ The Electron front includes stylesheets which we are building continuously with ### The Electron app -Wait until all the three previous ones are ready. Then e.g. on MacOS: - - ./electron/Electron.app/Contents/MacOS/Electron app/dev - - -### Running and Debugging the Production App - -The electron parts can be build with -1. `bin/build-electron-prod` and the jvm with -2. `lein uberjar`. + ./bin/build-stylesheets-prod -The next steps depend on the OS. On MacOS: -3. `bin/build-mac-os` -4. `./madek-exporter-darwin-x64/madek-exporter.app/Contents/MacOS/madek-exporter` ## Copyright and license @@ -82,4 +69,4 @@ Madek is (C) Zürcher Hochschule der Künste (Zurich University of the Arts). Madek is Free Software under the GNU General Public License (GPL) v3, see the included LICENSE file for license details. Visit our main website at http://www.zhdk.ch and the IT center -at http://itz.zhdk.ch \ No newline at end of file +at http://itz.zhdk.ch diff --git a/app/dev/releases.json b/app/dev/releases.json index 17e461c..055f413 100644 --- a/app/dev/releases.json +++ b/app/dev/releases.json @@ -1 +1 @@ -[{"version_major":0,"version_minor":9,"version_patch":7,"version_pre":null,"version_build":null,"name":null,"description":"WIP Fix missing permissions-parameter when recursing sets\n"},{"version_major":0,"version_minor":9,"version_patch":6,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Write meta-data.json and index.html twice: once with and once without prefix.\n\nFixes:\n------\n\n* Fix build on JDK9.\n"},{"version_major":0,"version_minor":9,"version_patch":5,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Download and store the meta-data schema (public vocabularies with meta-keys).\n* Export a index.html file for every entry.\n\nFixes:\n------\n\n* Sort meta-data in the same way as webapp.\n"},{"version_major":0,"version_minor":8,"version_patch":2,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Improve UI and UI when selecting the meta-key prefix.\n\nFixes:\n------\n\n* Fix recursive download of sets \"ArityException\"\n"},{"version_major":0,"version_minor":7,"version_patch":3,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Rename from \"Madek Exporter\" to \"Madek-Exporter\"\n\nFixes\n=====\n\n* Fix sign in as API-client.\n* Extend auth-info with type, show auth-info when connected as ApiClient.\n* Hide secrets by default: do not show \"internal\" connection parameters\n (password etc) in connection panel.\n"},{"version_major":0,"version_minor":6,"version_patch":0,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Improve the UX of the sign-in page: swapping tags deletes existing sign in info.\n\nFixes\n=====\n\n* Fix sign in with login and password.\n"},{"version_major":0,"version_minor":5,"version_patch":0,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Rename the application from \"Madek APP\" to \"Madek Exporter\".\n* Include release info.\n\nFixes\n=====\n\n* Fix export of meta-data of the Type MetaDatum::TextType.\n* Disconnect on the connection page will now delete the saved token, too.\n* Fix spelling and unnecessary involved language in many places.\n"}] \ No newline at end of file +[{"version_major":0,"version_minor":10,"version_patch":0,"version_pre":0,"version_build":null,"name":null,"description":"\nFixes and Features\n------------------\n\n* Fix certificate issues.\n* Fix html page with respect to roles.\n* Resolve and display role data within roles.\n* Resolve and display person data within roles.\n\nNotes\n-----\n\n* The exporter only supports Mac OS from this release on.\n* The CSS (re-)build doesn't work.\n"},{"version_major":0,"version_minor":9,"version_patch":7,"version_pre":null,"version_build":null,"name":null,"description":"WIP Fix missing permissions-parameter when recursing sets\n"},{"version_major":0,"version_minor":9,"version_patch":6,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Write meta-data.json and index.html twice: once with and once without prefix.\n\nFixes:\n------\n\n* Fix build on JDK9.\n"},{"version_major":0,"version_minor":9,"version_patch":5,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Download and store the meta-data schema (public vocabularies with meta-keys).\n* Export a index.html file for every entry.\n\nFixes:\n------\n\n* Sort meta-data in the same way as webapp.\n"},{"version_major":0,"version_minor":8,"version_patch":2,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Improve UI and UI when selecting the meta-key prefix.\n\nFixes:\n------\n\n* Fix recursive download of sets \"ArityException\"\n"},{"version_major":0,"version_minor":7,"version_patch":3,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Rename from \"Madek Exporter\" to \"Madek-Exporter\"\n\nFixes\n=====\n\n* Fix sign in as API-client.\n* Extend auth-info with type, show auth-info when connected as ApiClient.\n* Hide secrets by default: do not show \"internal\" connection parameters\n (password etc) in connection panel.\n"},{"version_major":0,"version_minor":6,"version_patch":0,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Improve the UX of the sign-in page: swapping tags deletes existing sign in info.\n\nFixes\n=====\n\n* Fix sign in with login and password.\n"},{"version_major":0,"version_minor":5,"version_patch":0,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Rename the application from \"Madek APP\" to \"Madek Exporter\".\n* Include release info.\n\nFixes\n=====\n\n* Fix export of meta-data of the Type MetaDatum::TextType.\n* Disconnect on the connection page will now delete the saved token, too.\n* Fix spelling and unnecessary involved language in many places.\n"}] \ No newline at end of file diff --git a/app/prod/releases.json b/app/prod/releases.json index 17e461c..055f413 100644 --- a/app/prod/releases.json +++ b/app/prod/releases.json @@ -1 +1 @@ -[{"version_major":0,"version_minor":9,"version_patch":7,"version_pre":null,"version_build":null,"name":null,"description":"WIP Fix missing permissions-parameter when recursing sets\n"},{"version_major":0,"version_minor":9,"version_patch":6,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Write meta-data.json and index.html twice: once with and once without prefix.\n\nFixes:\n------\n\n* Fix build on JDK9.\n"},{"version_major":0,"version_minor":9,"version_patch":5,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Download and store the meta-data schema (public vocabularies with meta-keys).\n* Export a index.html file for every entry.\n\nFixes:\n------\n\n* Sort meta-data in the same way as webapp.\n"},{"version_major":0,"version_minor":8,"version_patch":2,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Improve UI and UI when selecting the meta-key prefix.\n\nFixes:\n------\n\n* Fix recursive download of sets \"ArityException\"\n"},{"version_major":0,"version_minor":7,"version_patch":3,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Rename from \"Madek Exporter\" to \"Madek-Exporter\"\n\nFixes\n=====\n\n* Fix sign in as API-client.\n* Extend auth-info with type, show auth-info when connected as ApiClient.\n* Hide secrets by default: do not show \"internal\" connection parameters\n (password etc) in connection panel.\n"},{"version_major":0,"version_minor":6,"version_patch":0,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Improve the UX of the sign-in page: swapping tags deletes existing sign in info.\n\nFixes\n=====\n\n* Fix sign in with login and password.\n"},{"version_major":0,"version_minor":5,"version_patch":0,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Rename the application from \"Madek APP\" to \"Madek Exporter\".\n* Include release info.\n\nFixes\n=====\n\n* Fix export of meta-data of the Type MetaDatum::TextType.\n* Disconnect on the connection page will now delete the saved token, too.\n* Fix spelling and unnecessary involved language in many places.\n"}] \ No newline at end of file +[{"version_major":0,"version_minor":10,"version_patch":0,"version_pre":0,"version_build":null,"name":null,"description":"\nFixes and Features\n------------------\n\n* Fix certificate issues.\n* Fix html page with respect to roles.\n* Resolve and display role data within roles.\n* Resolve and display person data within roles.\n\nNotes\n-----\n\n* The exporter only supports Mac OS from this release on.\n* The CSS (re-)build doesn't work.\n"},{"version_major":0,"version_minor":9,"version_patch":7,"version_pre":null,"version_build":null,"name":null,"description":"WIP Fix missing permissions-parameter when recursing sets\n"},{"version_major":0,"version_minor":9,"version_patch":6,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Write meta-data.json and index.html twice: once with and once without prefix.\n\nFixes:\n------\n\n* Fix build on JDK9.\n"},{"version_major":0,"version_minor":9,"version_patch":5,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Download and store the meta-data schema (public vocabularies with meta-keys).\n* Export a index.html file for every entry.\n\nFixes:\n------\n\n* Sort meta-data in the same way as webapp.\n"},{"version_major":0,"version_minor":8,"version_patch":2,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Improve UI and UI when selecting the meta-key prefix.\n\nFixes:\n------\n\n* Fix recursive download of sets \"ArityException\"\n"},{"version_major":0,"version_minor":7,"version_patch":3,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Rename from \"Madek Exporter\" to \"Madek-Exporter\"\n\nFixes\n=====\n\n* Fix sign in as API-client.\n* Extend auth-info with type, show auth-info when connected as ApiClient.\n* Hide secrets by default: do not show \"internal\" connection parameters\n (password etc) in connection panel.\n"},{"version_major":0,"version_minor":6,"version_patch":0,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Improve the UX of the sign-in page: swapping tags deletes existing sign in info.\n\nFixes\n=====\n\n* Fix sign in with login and password.\n"},{"version_major":0,"version_minor":5,"version_patch":0,"version_pre":null,"version_build":null,"name":null,"description":"\nChanges\n=======\n\n* Rename the application from \"Madek APP\" to \"Madek Exporter\".\n* Include release info.\n\nFixes\n=====\n\n* Fix export of meta-data of the Type MetaDatum::TextType.\n* Disconnect on the connection page will now delete the saved token, too.\n* Fix spelling and unnecessary involved language in many places.\n"}] \ No newline at end of file diff --git a/bin/build-electron-front-prod b/bin/build-electron-front-prod new file mode 100755 index 0000000..1b2ffd5 --- /dev/null +++ b/bin/build-electron-front-prod @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/java-setup +${PROJECT_DIR}/bin/env/clojure-setup +${PROJECT_DIR}/bin/env/lein-setup + +rm -rf \ + app/prod/js/front.js \ + app/prod/js/out_front.js +#lein do \ + +lein externs electron-front-prod app/prod/js/front_externs.js + +lein cljsbuild once electron-front-prod diff --git a/bin/build-electron-main-prod b/bin/build-electron-main-prod new file mode 100755 index 0000000..d14c088 --- /dev/null +++ b/bin/build-electron-main-prod @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/java-setup +${PROJECT_DIR}/bin/env/clojure-setup +${PROJECT_DIR}/bin/env/lein-setup + +rm -rf \ + app/prod/js/out_main \ + app/prod/js/main.js + +lein externs electron-main-prod app/prod/js/main_externs.js + +lein cljsbuild once electron-main-prod + diff --git a/bin/build-electron-prod b/bin/build-electron-prod index 8a3a034..e561e0a 100755 --- a/bin/build-electron-prod +++ b/bin/build-electron-prod @@ -1,13 +1,8 @@ #!/usr/bin/env bash -set -eou -rm -rf \ - app/prod/js/out_main \ - app/prod/js/main.js \ - app/prod/js/front.js \ - app/prod/js/out_front.js -lein do \ - externs electron-main-prod app/prod/js/main_externs.js, \ - cljsbuild once electron-main-prod, \ - externs electron-front-prod app/prod/js/front_externs.js, \ - cljsbuild once electron-front-prod, \ - with-profile prod sass once +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" + +${PROJECT_DIR}/bin/build-electron-main-prod +${PROJECT_DIR}/bin/build-electron-front-prod +${PROJECT_DIR}/bin/build-stylesheets-prod diff --git a/bin/build-jvm-main-prod b/bin/build-jvm-main-prod index 4a0f8fc..d817fa8 100755 --- a/bin/build-jvm-main-prod +++ b/bin/build-jvm-main-prod @@ -1,2 +1,9 @@ #!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/lein-setup +${PROJECT_DIR}/bin/env/clojure-setup +${PROJECT_DIR}/bin/env/java-setup + lein uberjar diff --git a/bin/build-linux b/bin/build-linux index d321ac5..72fdb5a 100755 --- a/bin/build-linux +++ b/bin/build-linux @@ -1,9 +1,15 @@ #!/usr/bin/env bash -set -eoux +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" + +cd $PROJECT_DIR + +rm -rf madek-exporter-linux-x64 npx electron-packager \ --overwrite --platform=linux --arch=x64 --electron-version=1.6.0 \ --icon=Madek.icns \ ./app/prod madek-exporter -cp -Lrf vendor/jre_linux ./madek-exporter-linux-x64/resources/jre +cp -Lrf vendor/jre_linux_x64 ./madek-exporter-linux-x64/resources/jre diff --git a/bin/build-mac-os b/bin/build-mac-os index 6f8d118..21793e7 100755 --- a/bin/build-mac-os +++ b/bin/build-mac-os @@ -1,10 +1,17 @@ #!/usr/bin/env bash -set -eoux +set -euo pipefail rm -rf ./madek-exporter-darwin-x64 +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" + +cd ${PROJECT_DIR} + +# ./bin/env/python-setup +./bin/env/nodejs-setup + npx electron-packager \ --overwrite --platform=darwin --arch=x64 --electron-version=1.6.0 \ --icon=Madek.icns \ ./app/prod madek-exporter -cp -Lrf vendor/jre_darwin/Contents/Home ./madek-exporter-darwin-x64/madek-exporter.app/Contents/Resources/jre +cp -Lrf ${PROJECT_DIR}/vendor/jre_macosx_x64 ./madek-exporter-darwin-x64/madek-exporter.app/Contents/Resources/jre diff --git a/bin/build-stylesheets-prod b/bin/build-stylesheets-prod index 302cd17..04a4b6a 100755 --- a/bin/build-stylesheets-prod +++ b/bin/build-stylesheets-prod @@ -1,3 +1,7 @@ #!/usr/bin/env bash -set -euxo -npx sass -s compressed --no-source-map electron_front/sass/site.sass app/prod/css/site.css +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/nodejs-setup + +${PROJECT_DIR}/bin/npx sass -s compressed --no-source-map electron_front/sass/site.sass app/prod/css/site.css diff --git a/bin/build-win b/bin/build-win index 8809856..bd1003b 100755 --- a/bin/build-win +++ b/bin/build-win @@ -1,6 +1,11 @@ #!/usr/bin/env bash -set -eoux -rm -rf ./madek-exporter-win32-x64 +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" + +cd $PROJECT_DIR + +rm -rf madek-exporter-win32-x64 npx electron-packager \ @@ -8,4 +13,4 @@ npx electron-packager \ --icon=Madek.icns \ ./app/prod madek-exporter -cp -Lrf vendor/jre_win ./madek-exporter-win32-x64/resources/jre +cp -Lrf vendor/jre_win_x64 ./madek-exporter-win32-x64/resources/jre diff --git a/bin/cljfmt-fix b/bin/cljfmt-fix new file mode 100755 index 0000000..c1b4bfb --- /dev/null +++ b/bin/cljfmt-fix @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/lein-setup +${PROJECT_DIR}/bin/env/clojure-setup +${PROJECT_DIR}/bin/env/java-setup + +lein cljfmt fix jvm_main/src project.clj + +#vi ft=sh diff --git a/bin/draft-gh-release b/bin/draft-gh-release index 506cbc3..a9ded43 100755 --- a/bin/draft-gh-release +++ b/bin/draft-gh-release @@ -68,7 +68,7 @@ end upload_url_template = Addressable::Template.new(created_release.body["upload_url"]) -%w(Madek-Exporter_Linux.zip Madek-Exporter_Mac-OS.zip Madek-Exporter_Windows.zip).each do |filename| +%w(Madek-Exporter_Linux.zip Madek-Exporter_Mac-OS.zip).each do |filename| url = upload_url_template.expand(name: filename).to_s file_content = IO.binread(filename) uploaded = conn.post do |req| diff --git a/bin/env/asdf-helper.bash b/bin/env/asdf-helper.bash new file mode 100644 index 0000000..6684212 --- /dev/null +++ b/bin/env/asdf-helper.bash @@ -0,0 +1,32 @@ +function mtime-comps() { + case "$(uname -s)" in + Linux*) date -Iseconds --date="$(stat -c '@%Y' $1)" ;; + Darwin) stat -f %Sm -t "%Y-%m-%dT%H:%M:%S%z" $1 ;; + esac +} + + +function asdf-update-plugin () { + # check asdf is present + CACHE_ID="${PLUGIN}_${PROJECT}" + echo "# ${CACHE_ID} env check via asdf $(asdf --version)" + TMPDIR=${TMPDIR:-/tmp/} + CACHE_FILE="${TMPDIR}asdf_cache_${CACHE_ID}" + + if [[ ! -e $CACHE_FILE ]] || [[ $(mtime-comps $CACHE_FILE) < $(mtime-comps .tool-versions) ]] ; then + if $(asdf plugin list | grep -q $PLUGIN); then + echo "asdf $PLUGIN found: updating " + asdf plugin update $PLUGIN + else + echo "asdf $PLUGIN NOT found: installing " + asdf plugin add $PLUGIN ${PLUGIN_URL} + fi + cd $PROJECT_DIR + asdf install $PLUGIN + touch $CACHE_FILE + echo "# ${CACHE_ID} env is up to date" + else + echo "# ${CACHE_ID} env skipped update; touch .tool-versions or remove ${CACHE_FILE} to force update" + fi +} +# vi: ft=sh diff --git a/bin/env/clojure-setup b/bin/env/clojure-setup new file mode 100755 index 0000000..3ad483c --- /dev/null +++ b/bin/env/clojure-setup @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd ../.. > /dev/null 2>&1 && pwd -P)" +PROJECT=madek-exporter +PLUGIN=clojure +PLUGIN_URL=https://github.com/asdf-community/asdf-clojure.git + +source $PROJECT_DIR/bin/env/asdf-helper.bash +asdf-update-plugin + +# vi: ft=sh diff --git a/bin/env/java-setup b/bin/env/java-setup new file mode 100755 index 0000000..11ecb41 --- /dev/null +++ b/bin/env/java-setup @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd ../.. > /dev/null 2>&1 && pwd -P)" +PROJECT=madek-exporter +PLUGIN=java +PLUGIN_URL=https://github.com/halcyon/asdf-java.git + +source $PROJECT_DIR/bin/env/asdf-helper.bash +asdf-update-plugin + +# vi: ft=sh diff --git a/bin/env/lein-setup b/bin/env/lein-setup new file mode 100755 index 0000000..f5cf143 --- /dev/null +++ b/bin/env/lein-setup @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd ../.. > /dev/null 2>&1 && pwd -P)" +PROJECT=madek-exporter +PLUGIN=lein +PLUGIN_URL=https://github.com/miorimmax/asdf-lein + +source $PROJECT_DIR/bin/env/asdf-helper.bash +asdf-update-plugin + +# vi: ft=sh diff --git a/bin/env/nodejs-setup b/bin/env/nodejs-setup new file mode 100755 index 0000000..fc62ec1 --- /dev/null +++ b/bin/env/nodejs-setup @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail +set -x + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd ../.. > /dev/null 2>&1 && pwd -P)" +PROJECT=madek-exporter +PLUGIN=nodejs +PLUGIN_URL=https://github.com/asdf-vm/asdf-nodejs.git + +source $PROJECT_DIR/bin/env/asdf-helper.bash +asdf-update-plugin + +# vi: ft=sh diff --git a/bin/env/python-setup b/bin/env/python-setup new file mode 100755 index 0000000..c073f78 --- /dev/null +++ b/bin/env/python-setup @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd ../.. > /dev/null 2>&1 && pwd -P)" +PROJECT=madek-exporter +PLUGIN=python +PLUGIN_URL=https://github.com/asdf-community/asdf-python.git + +source $PROJECT_DIR/bin/env/asdf-helper.bash +asdf-update-plugin + +# vi: ft=sh diff --git a/bin/env/ruby-setup b/bin/env/ruby-setup new file mode 100755 index 0000000..05db0fa --- /dev/null +++ b/bin/env/ruby-setup @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd ../.. > /dev/null 2>&1 && pwd -P)" +PROJECT=madek-exporter +PLUGIN=ruby +PLUGIN_URL=https://github.com/asdf-vm/asdf-ruby.git + +source $PROJECT_DIR/bin/env/asdf-helper.bash +asdf-update-plugin + +bundle install --quiet +# vi: ft=sh diff --git a/bin/lein b/bin/lein new file mode 100755 index 0000000..6d7f081 --- /dev/null +++ b/bin/lein @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/lein-setup +${PROJECT_DIR}/bin/env/clojure-setup +${PROJECT_DIR}/bin/env/java-setup + +lein "$@" + +#vi ft=sh diff --git a/bin/npx b/bin/npx new file mode 100755 index 0000000..2966c42 --- /dev/null +++ b/bin/npx @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/nodejs-setup + +npx "$@" + +#vi ft=sh diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 0000000..14a3728 --- /dev/null +++ b/bin/rspec @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/ruby-setup + +bundle exec rspec "$@" + +#vi ft=sh diff --git a/bin/ruby b/bin/ruby new file mode 100755 index 0000000..cb627c9 --- /dev/null +++ b/bin/ruby @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd -- "$(dirname "${BASH_SOURCE}")" ; cd .. > /dev/null 2>&1 && pwd -P)" +${PROJECT_DIR}/bin/env/ruby-setup + +ruby "$@" + +#vi ft=sh diff --git a/cider-ci.yml b/cider-ci.yml index 9ba1dcd..6c4d10b 100644 --- a/cider-ci.yml +++ b/cider-ci.yml @@ -8,10 +8,7 @@ jobs: context: tasks: build: - include: - - cider-ci/environment_variables.yml - traits: - ubuntu-desktop: true + traits: [] scripts: include: - cider-ci/bundle-script.yml @@ -20,8 +17,8 @@ jobs: bundle has passed: script_key: bundle body: | - set -euxo - export PATH=~/.rubies/$RUBY/bin:$PATH + #!/usr/bin/env bash + set -euo pipefail bundle exec ./bin/update-releases git diff --stat --exit-code -- app/prod/releases.json @@ -36,8 +33,7 @@ jobs: release: include: - cider-ci/build-and-test.yml - traits: - ci-g2018-04: true + traits: {} scripts: # override the existing test; we don't care about the result test: @@ -46,14 +42,14 @@ jobs: start_when: build-linux has passed: script_key: build-linux - build-windows has passed: - script_key: build-windows +# build-windows has passed: +# script_key: build-windows build-mac-os has passed: script_key: build-mac-os timeout: 10 Minutes body: | - set -euxo - export PATH=~/.rubies/$RUBY/bin:$PATH + #!/usr/bin/env bash + set -euo pipefail bundle exec ./bin/draft-gh-release build: diff --git a/cider-ci/build-and-test.yml b/cider-ci/build-and-test.yml index 97b03eb..21248a9 100644 --- a/cider-ci/build-and-test.yml +++ b/cider-ci/build-and-test.yml @@ -1,5 +1,3 @@ -include: - - cider-ci/environment_variables.yml git_options: submodules: include_match: ^.*$ @@ -11,20 +9,20 @@ trial_attachments: include_match: 'logs\/.+\.log$' content_type: text/plain traits: - JDK: true - Leiningen: true - libgconf-2-4: true - nodejs: true - #nx-07288_linux-vm: true - ubuntu-desktop: true - ruby-install: true - wine: true - xorg: true + asdf: true + ci-executor-madek: true + # libgconf-2-4: true + # ubuntu-desktop: true + # wine: true + # xorg: true scripts: include: - cider-ci/bundle-script.yml install-npm-packages: - body: npm clean-install + body: | + #!/usr/bin/env bash + ./bin/env/nodejs-setup + npm clean-install build-stylesheets: body: bin/build-stylesheets-prod* start_when: @@ -32,24 +30,24 @@ scripts: script_key: install-npm-packages build-electron-front: body: | - set -eoux - lein do \ - externs electron-front-prod app/prod/js/front_externs.js, \ - cljsbuild once electron-front-prod + #!/usr/bin/env bash + set -euo pipefail + ./bin/build-electron-front-prod start_when: install-npm-packages has passed: script_key: install-npm-packages build-electron-main: body: | - set -eoux - lein do \ - externs electron-main-prod app/prod/js/main_externs.js, \ - cljsbuild once electron-main-prod + #!/usr/bin/env bash + set -euo pipefail + ./bin/build-electron-main-prod start_when: install-npm-packages has passed: script_key: install-npm-packages build-jvm-main: - body: lein uberjar + body: | + #!/usr/bin/env bash + ./bin/build-jvm-main-prod build-components-done: # just a meta script to model dependencies easier body: exit 0 @@ -64,16 +62,20 @@ scripts: script_key: build-stylesheets build-mac-os: body: | - set -eoux + #!/usr/bin/env bash + set -euo pipefail ./bin/build-mac-os zip -r Madek-Exporter_Mac-OS.zip madek-exporter-darwin-x64 - # cp Madek-Exporter_Mac-OS.zip /tmp/Madek-Exporter_Mac-OS_${CIDER_CI_TREE_ID}.zip + cp Madek-Exporter_Mac-OS.zip /tmp/Madek-Exporter_Mac-OS_${CIDER_CI_TREE_ID}.zip start_when: build-components has passed: script_key: build-components-done build-windows: + ignore_state: true body: | - set -eoux + #!/usr/bin/env bash + set -euo pipefail + echo "THE STATE OF THIS SCRIPT IS IGNORED SINCE THE WINDOWS BUILD FAILS ON NEWER SYSTEMS" ./bin/build-win zip -r Madek-Exporter_Windows.zip madek-exporter-win32-x64 # cp Madek-Exporter_Linux.zip /tmp/Madek-Exporter_Linux_${CIDER_CI_TREE_ID}.zip @@ -83,7 +85,8 @@ scripts: script_key: build-components-done build-linux: body: | - set -eoux + #!/usr/bin/env bash + set -euo pipefail ./bin/build-linux zip -r Madek-Exporter_Linux.zip madek-exporter-linux-x64 # cp Madek-Exporter_Linux.zip /tmp/Madek-Exporter_Linux_${CIDER_CI_TREE_ID}.zip @@ -91,6 +94,7 @@ scripts: build-components has passed: script_key: build-components-done test: + ignore_state: true start_when: bundle has passed: script_key: bundle @@ -98,9 +102,8 @@ scripts: script_key: build-linux body: | #!/usr/bin/env bash - set -eux - export PATH=~/.rubies/$RUBY/bin:$PATH - mkdir -p logs - xvfb-run -a -e logs/xvfb.log \ - bundle exec rspec - + set -euo pipefail + echo "THE STATE OF THIS SCRIPT IS IGNORED SINCE THE CHROMEDRIVER CRASHES ON NEWER SYSTEMS" + which chromedriver + chromedriver --version + xvfb-run -a -e logs/xvfb.log ./bin/rspec spec diff --git a/cider-ci/bundle-script.yml b/cider-ci/bundle-script.yml index 036c5f7..c6362b2 100644 --- a/cider-ci/bundle-script.yml +++ b/cider-ci/bundle-script.yml @@ -1,19 +1,8 @@ bundle: - exclusive_executor_resource: ruby-install_{{$RUBY}} + exclusive_executor_resource: asdf-ruby timeout: 20 Minutes body: | #!/usr/bin/env bash - set -eux - export PATH=~/.rubies/$RUBY/bin:$PATH + set -euo pipefail + ./bin/env/ruby-setup - rm -f .bundle/config - - if [ ! -d ~/.rubies/$RUBY ]; then - ruby-install --no-install-deps $RUBY_ENGINE $RUBY_VERSION - fi - - if [ ! -f ~/.rubies/$RUBY/bin/bundle ]; then - gem install bundler - fi - - bundle install diff --git a/cider-ci/environment_variables.yml b/cider-ci/environment_variables.yml deleted file mode 100644 index 14ccd7b..0000000 --- a/cider-ci/environment_variables.yml +++ /dev/null @@ -1,5 +0,0 @@ -environment_variables: - RUBY_ENGINE: ruby - RUBY_VERSION: 2.6.3 - RUBY: '{{RUBY_ENGINE}}-{{RUBY_VERSION}}' - diff --git a/electron_main/src/all/madek/app/main/jvm_main_process.cljs b/electron_main/src/all/madek/app/main/jvm_main_process.cljs index 621cdf8..ba49007 100644 --- a/electron_main/src/all/madek/app/main/jvm_main_process.cljs +++ b/electron_main/src/all/madek/app/main/jvm_main_process.cljs @@ -23,6 +23,7 @@ (reset! jvm-main-process-child (.spawn child-process java-path (clj->js ["-jar" jar-path + "server" "-p" env/jvm-port "-s" env/jvm-password]))) (.on @jvm-main-process-child "error" #(.log js/console (str "JVM-MAIN_PROC-ERR " %))) diff --git a/jvm_main/src/madek/app/server/connection.clj b/jvm_main/src/madek/app/server/connection.clj deleted file mode 100644 index 3db0b24..0000000 --- a/jvm_main/src/madek/app/server/connection.clj +++ /dev/null @@ -1,69 +0,0 @@ -(ns madek.app.server.connection - (:require - [madek.app.server.utils :as utils] - [madek.app.server.state :as state] - [json-roa.client.core :as roa] - - [clj-time.core :as time] - [clj-time.format :as time-format] - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - [logbug.debug :as debug] - [logbug.thrown :as thrown] - )) - -(defn auth-info [api-entry-point api-http-opts] - (let [response (-> (roa/get-root api-entry-point :default-conn-opts api-http-opts) - (roa/relation :auth-info) - (roa/get {}))] - (logging/debug (-> response roa/data)) - response)) - -(defn connect-to-madek-server [request] - (catcher/snatch - {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} - (logging/debug 'connect {:request request}) - (try (let [connect-body (:body request) - url (-> connect-body :url) - http-options (utils/options-to-http-options connect-body) - api-root (roa/get-root (str url "/api/") - :default-conn-opts http-options) - auth-info (when (:basic-auth http-options) - (-> api-root (roa/relation :auth-info) (roa/get {})))] - (logging/debug 'http-options http-options) - (logging/debug 'api-root api-root) - (logging/debug 'auth-info auth-info) - (if-not auth-info - {:status 422 :body {:message (str "no auth-info response, " - "check your connection parameters.")}} - (let [response-status (:status auth-info)] - (logging/debug 'auth-info auth-info) - (logging/debug 'response-status response-status) - (if-not (and (>= response-status 200) (< response-status 300)) - {:status response-status :body {:message "Authentication failed"}} - (let [auth-info (roa/data auth-info)] - (swap! state/db - (fn [db conn-params] - (assoc-in db [:connection] conn-params)) - (merge - (select-keys connect-body [:url]) - {:http-options http-options - :auth-info auth-info} - (select-keys auth-info [:login :email_address]))) - {:status 202}))))) - (catch Exception e - (cond - (= (-> e ex-data :status) 401) {:status 401 - :body "Authentication failed. Check your credentials!"} - :else (throw e)))))) - -(defn disconnect [_] - (swap! state/db assoc-in [:connection] {})) - -;### Debug #################################################################### -;(logging-config/set-logger! :level :debug) -;(logging-config/set-logger! :level :info) -;(debug/debug-ns 'ring.middleware.resource) -;(debug/debug-ns *ns*) diff --git a/jvm_main/src/madek/app/server/export/meta_data.clj b/jvm_main/src/madek/app/server/export/meta_data.clj deleted file mode 100644 index 9312817..0000000 --- a/jvm_main/src/madek/app/server/export/meta_data.clj +++ /dev/null @@ -1,80 +0,0 @@ -(ns madek.app.server.export.meta-data - (:require - [madek.app.server.state :as state] - [json-roa.client.core :as roa] - [madek.app.server.utils :refer [deep-merge]] - - [cheshire.core :as cheshire] - [clojure.java.io :as io] - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - [logbug.thrown :as thrown] - [logbug.debug :as debug :refer [I> I>>]] - ) - - (:import - [java.io File])) - - -;### meta data ################################################################ - -(defn get-meta-data-for-md-relation-type [md] - (-> md (roa/get {}) - roa/data)) - -(defn get-collection-meta-datum-values [meta-datum] - (merge (-> meta-datum roa/data - (dissoc :value)) - {:values (->> meta-datum - roa/coll-seq - (map get-meta-data-for-md-relation-type))})) - -(defn get-scalar-meta-datum-value [meta-datum] - (-> meta-datum - roa/data)) - -(defn meta-data_unmemoized [media-resource] - (->> (-> media-resource - (roa/relation :meta-data) - (roa/get {}) - roa/coll-seq) - (map #(roa/get % {})) - (map (fn [meta-datum] - (case (-> meta-datum roa/data :type) - ("MetaDatum::Text" "MetaDatum::TextDate") (get-scalar-meta-datum-value meta-datum) - (get-collection-meta-datum-values meta-datum) - ))))) - -(def meta-data (memoize meta-data_unmemoized)) - -(defn title [meta-data] - (:value (some (fn [meta-datum] - (and (= "madek_core:title" (:meta_key_id meta-datum)) - meta-datum)) - meta-data))) - -(defn write-meta-data [target-dir meta-data item-id prefix-path] - (let [content (cheshire/generate-string meta-data {:pretty true})] - (doseq [path [(str target-dir File/separator "meta-data.json") - (str target-dir File/separator prefix-path "_meta-data.json")]] - (io/make-parents path) - (spit path content) - (swap! state/db - (fn [db params] - (deep-merge db params)) - {:download - {:items - {item-id - {:title (title meta-data) - :meta-data - {:path path - :data meta-data }}}}})))) - -;### Debug #################################################################### -;(logging-config/set-logger! :level :debug) -;(logging-config/set-logger! :level :info) -;(debug/debug-ns 'ring.middleware.resource) -;(debug/debug-ns *ns*) - diff --git a/jvm_main/src/madek/app/server/scratch.clj b/jvm_main/src/madek/app/server/scratch.clj deleted file mode 100644 index a84c5fc..0000000 --- a/jvm_main/src/madek/app/server/scratch.clj +++ /dev/null @@ -1,12 +0,0 @@ -(ns madek.app.server.scratch - (:require - [clojure.data :refer :all] - [timothypratley.patchin :as patchin] - )) - - -(patchin/diff {:ar [1 1 3 4 5 6] :x :y :a {:b 7 :c {:d 42 :k :keep :e :removed}}} - {:ar [1 2 3 4 5 6] :x :y :a {:b 7 :c {:d :changed :k :keep }}}) - - - diff --git a/jvm_main/src/madek/app/server/web.clj b/jvm_main/src/madek/app/server/web.clj deleted file mode 100644 index da867c2..0000000 --- a/jvm_main/src/madek/app/server/web.clj +++ /dev/null @@ -1,266 +0,0 @@ -(ns madek.app.server.web - (:refer-clojure :exclude [str keyword ]) - - (:require - - [madek.app.server.connection :as connection] - [madek.app.server.export :as export] - [madek.app.server.state :as state] - [madek.app.server.utils :as utils :refer [str keyword deep-merge presence]] - - [inflections.core :refer [capitalize]] - [cheshire.core :as cheshire] - [clj-http.client :as http-client] - [clojure.data.json :as json] - [clojure.pprint :refer [pprint]] - [compojure.core :refer [ANY GET PATCH POST DELETE defroutes]] - [compojure.route :refer [not-found resources]] - [environ.core :refer [env]] - [hiccup.core :refer [html]] - [hiccup.page :refer [include-js include-css]] - [json-roa.client.core :as roa] - [ring.middleware.defaults :refer [site-defaults wrap-defaults]] - [ring.middleware.json] - [ring.util.response :refer [response]] - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - [logbug.thrown :as thrown] - [logbug.debug :as debug :refer [I> I>>]] - [logbug.ring :as logbug-ring :refer [wrap-handler-with-logging]] - - )) - - -;### download entity ########################################################## - -(defn download-step1 [request] - (catcher/snatch - {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} - (let [http-options (-> @state/db :connection :http-options) - id (-> request :body :entity-id) - entity-type (case (-> request :body :entity-type) - "entry" :media-entry - "set" :collection) - entity (-> (roa/get-root (str (-> @state/db :connection :url) "/api") - :default-conn-opts (-> @state/db :connection :http-options)) - (roa/relation entity-type) - (roa/get {:id id})) - title (-> entity - (roa/relation :meta-data) - (roa/get {:meta_keys (json/write-str ["madek_core:title"])}) - roa/coll-seq first (roa/get {}) roa/data :value)] - (do (swap! state/db - (fn [db dl-entity target-dir] - (deep-merge db - {:download - {:step1-completed true - :entity dl-entity - :target-directory target-dir}})) - {:title title - :uuid id - :type entity-type - :url (-> request :body :url)} - (-> request :body :target-directory)) - {:status 204})))) - -;(pprint @state/db) - - -;### set options ############################################################## - -(defn patch-download [request] - (catcher/snatch - {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} - (swap! state/db - (fn [db body] - (assoc-in db [:download] - (deep-merge (:download db) - body))) - (:body request)) - {:status 204})) - -;############################################################################## - -(defonce download-future (atom nil)) - -(def snatch-dl-exception-params - {:return-fn (fn [e] - (swap! state/db - (fn [db e] - (deep-merge db - {:download - {:state :failed - :errors {:dowload-error (str e)}}})) - e)) - :throwable Throwable}) - -(defn start-download-future [id target-dir recursive? skip-media-files? prefix-meta-key entry-point http-options] - (reset! download-future - (future - (catcher/snatch - {:return-fn (fn [e] - (swap! state/db - (fn [db e] - (deep-merge db - {:download - {:download-finished true - :errors {:dowload-error (str e)}}})) - e)) - :throwable Throwable} - (case (-> @state/db :download :entity :type) - :collection (export/download-set - id target-dir recursive? skip-media-files? - prefix-meta-key entry-point http-options) - :media-entry (export/download-media-entry - id target-dir skip-media-files? prefix-meta-key - entry-point http-options)) - (swap! state/db (fn [db] (assoc-in db [:download :download-finished] true))))))) - -(defn download [request] - (if (and @download-future (not (realized? @download-future))) - {:status 422 :body "There seems to be an ongoing download in progress!"} - (catcher/snatch - {:return-fn (fn [e] - (swap! state/db - (fn [db e] - (deep-merge db - {:download - {:download-finished true - :errors {:dowload-error (str e)}}})) - e)) - :throwable Throwable} - (swap! state/db (fn [db] (assoc-in db [:download :download-started] true))) - (let [id (-> @state/db :download :entity :uuid) - target-dir (-> @state/db :download :target-directory) - recursive? (-> @state/db :download :recursive not not) - skip-media-files? (-> @state/db :download :skip_media_files not not) - download-meta-data-schema? true - prefix-meta-key (-> @state/db :download :prefix_meta_key presence) - entry-point (state/connection-entry-point) - http-options (state/connection-http-options)] - (when download-meta-data-schema? - (export/download-meta-data-schema target-dir)) - (start-download-future id target-dir recursive? skip-media-files? prefix-meta-key entry-point http-options)) - {:status 202}))) - -(defn patch-download-item [request] - (logging/debug 'patch-download-item {:request request}) - (let [item-id (-> request :route-params :id) - patch-params (-> request :body)] - (swap! state/db - (fn [db item-id patch-params] - (let [item-params (or (-> db :download :items (get item-id)) {})] - (assoc-in db [:download :items item-id] - (deep-merge item-params - patch-params)))) - item-id patch-params)) - {:status 204}) - -(defn delete-download [_] - (swap! state/db (fn [db] - (dissoc db :download :download-entity))) - {:status 204}) - -;############################################################################## - -(defn patch-download-parameters [request] - (logging/debug 'patch-download-parameters {:request request}) - (swap! state/db - (fn [db params] - (deep-merge db - {:download-parameters params})) - (:body request)) - {:status 204}) - -;############################################################################## - -(defn open [request] - (logging/debug request) - (utils/os-browse (-> request :body :uri)) - {:status 201}) - -;############################################################################## - -(defn shutdown [request] - (future - (Thread/sleep 3000) - (System/exit 0)) - "Good Bye!") - -;############################################################################## - - -(defn vocabularies [_] - (catcher/snatch - {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} - (let [http-options (-> @state/db :connection :http-options) - vocabularies (->> (-> (roa/get-root (str (-> @state/db :connection :url) "/api") - :default-conn-opts (-> @state/db :connection :http-options)) - (roa/relation :vocabularies) - (roa/get {}) - roa/coll-seq) - (map #(roa/get % {})) - (map roa/data))] - (response vocabularies)))) - -(defn meta-keys [vocabulary] - (catcher/snatch - {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} - (let [http-options (-> @state/db :connection :http-options) - meta-keys (->> (-> (roa/get-root (str (-> @state/db :connection :url) "/api") - :default-conn-opts (-> @state/db :connection :http-options)) - (roa/relation :meta-keys) - (roa/get {:vocabulary vocabulary}) - roa/coll-seq) - (map #(roa/get % {})) - (map roa/data))] - (response meta-keys)))) - -;############################################################################## - -(defroutes routes - - (DELETE "/download" _ #'delete-download) - - (POST "/connect" _ #'connection/connect-to-madek-server) - (DELETE "/connect" _ #'connection/disconnect) - - (POST "/open" _ #'open) - - (PATCH "/download" _ #'patch-download) - - (PATCH "/download/items/:id" _ #'patch-download-item) - - (PATCH "/download-parameters" _ #'patch-download-parameters) - - (POST "/download" _ #'download) - - (POST "/download/step1" _ #'download-step1) - - (ANY "/shutdown" _ #'shutdown) - - (GET "/vocabularies/" _ #'vocabularies) - (GET "/vocabularies/:vocabulary/meta-keys/" - [vocabulary] (#'meta-keys vocabulary)) - - (resources "/") - - (not-found "Not Found")) - -(def app - (I> wrap-handler-with-logging - routes - state/wrap - ring.middleware.json/wrap-json-response - (wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false)) - (ring.middleware.json/wrap-json-body {:keywords? true}) - ring.middleware.keyword-params/wrap-keyword-params - ring.middleware.params/wrap-params)) - -;### Debug #################################################################### -;(logging-config/set-logger! :level :debug) -;(logging-config/set-logger! :level :info) -;(debug/debug-ns 'ring.middleware.resource) -;(debug/debug-ns *ns*) diff --git a/jvm_main/src/madek/exporter/cli_run.clj b/jvm_main/src/madek/exporter/cli_run.clj new file mode 100644 index 0000000..7921fe1 --- /dev/null +++ b/jvm_main/src/madek/exporter/cli_run.clj @@ -0,0 +1,61 @@ +(ns madek.exporter.cli-run + (:require + [clojure.pprint :refer [pprint]] + [clojure.string] + [clojure.tools.cli :as cli] + [environ.core :refer [env]] + [madek.exporter.connection :refer [connect-to-madek-server]] + [madek.exporter.export :as export] + [madek.exporter.state :as state] + [taoensso.timbre :as timbre :refer [info debug warn error]])) + +(def cli-options + [["-u" "--madek-url URL" "Madek URL" + :default (or (env :madek-url) "https://staging.madek.zhdk.ch")] + ["-d" "--download-dir DIRECTORY" "Download directory" + :default (clojure.string/join java.io.File/separator + [(System/getProperty "user.home") + "Downloads" "Madek"])] + [nil "--media-entry-id MEDIA-ENTRY-ID"] + [nil "--token TOKEN"] + ["-h" "--help"]]) + +(defn main-usage [options-summary & more] + (->> ["Usage: madek-exporter cli " + "" + options-summary + "" + "" + (when more + ["-------------------------------------------------------------------" + (with-out-str (pprint more)) + "-------------------------------------------------------------------"])] + flatten + (clojure.string/join \newline))) + +(defn run [options] + (info 'run options) + (connect-to-madek-server {:body {:password (:token options) + :url (:madek-url options)}}) + (info 'state/db @state/db) + (when-let [media-entry-id (:media-entry-id options)] + (export/download-media-entry + media-entry-id + "" + (str (-> @state/db :connection :url) "/api") + (-> @state/db :connection :http-options)))) + +(defn main [global-options args] + (try + (let [{:keys [options arguments errors summary]} + (cli/parse-opts args cli-options :in-order true) + cmd (some-> arguments first keyword) + pass-on-args (->> (rest arguments) flatten (into [])) + options (into (sorted-map) options) + print-summary #(println (main-usage summary {:args args :options options}))] + (info {'args args 'options options 'cmd cmd 'pass-on-args pass-on-args}) + (cond + (:help options) (print-summary) + :else (run (merge global-options options)))) + (catch Exception ex + (error ex)))) diff --git a/jvm_main/src/madek/exporter/connection.clj b/jvm_main/src/madek/exporter/connection.clj new file mode 100644 index 0000000..16a2230 --- /dev/null +++ b/jvm_main/src/madek/exporter/connection.clj @@ -0,0 +1,65 @@ +(ns madek.exporter.connection + (:require + [clj-time.core :as time] + [clj-time.format :as time-format] + [json-roa.client.core :as roa] + [logbug.catcher :as catcher] + [logbug.debug :as debug] + [logbug.thrown :as thrown] + [madek.exporter.state :as state] + [madek.exporter.utils :as utils] + [taoensso.timbre :as timbre :refer [info debug]])) + +(defn auth-info [api-entry-point api-http-opts] + (let [response (-> (roa/get-root api-entry-point :default-conn-opts api-http-opts) + (roa/relation :auth-info) + (roa/get {}))] + (debug (-> response roa/data)) + response)) + +(defn connect-to-madek-server [request] + (catcher/snatch + {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} + (debug 'connect {:request request}) + (try (let [connect-body (:body request) + url (-> connect-body :url) + http-options (utils/options-to-http-options connect-body) + api-root (roa/get-root (str url "/api/") + :default-conn-opts http-options) + auth-info (when (:basic-auth http-options) + (-> api-root (roa/relation :auth-info) (roa/get {})))] + (debug 'http-options http-options) + (debug 'api-root api-root) + (debug 'auth-info auth-info) + (if-not auth-info + {:status 422 :body {:message (str "no auth-info response, " + "check your connection parameters.")}} + (let [response-status (:status auth-info)] + (debug 'auth-info auth-info) + (debug 'response-status response-status) + (if-not (and (>= response-status 200) (< response-status 300)) + {:status response-status :body {:message "Authentication failed"}} + (let [auth-info (roa/data auth-info)] + (swap! state/db + (fn [db conn-params] + (assoc-in db [:connection] conn-params)) + (merge + (select-keys connect-body [:url]) + {:http-options http-options + :auth-info auth-info} + (select-keys auth-info [:login :email_address]))) + {:status 202}))))) + (catch Exception e + (cond + (= (-> e ex-data :status) 401) {:status 401 + :body "Authentication failed. Check your credentials!"} + :else (throw e)))))) + +(defn disconnect [_] + (swap! state/db assoc-in [:connection] {})) + +;### Debug #################################################################### +;(logging-config/set-logger! :level :debug) +;(logging-config/set-logger! :level :info) +;(debug/debug-ns 'ring.middleware.resource) +;(debug/debug-ns *ns*) diff --git a/jvm_main/src/madek/app/server/export.clj b/jvm_main/src/madek/exporter/export.clj similarity index 72% rename from jvm_main/src/madek/app/server/export.clj rename to jvm_main/src/madek/exporter/export.clj index 8bfbb93..582a526 100644 --- a/jvm_main/src/madek/app/server/export.clj +++ b/jvm_main/src/madek/exporter/export.clj @@ -1,30 +1,23 @@ -(ns madek.app.server.export +(ns madek.exporter.export (:require - [madek.app.server.export.files :as files :refer [download-media-files path-prefix]] - [madek.app.server.export.index-html :as index-html] - [madek.app.server.export.meta-data :as meta-data :refer [meta-data write-meta-data]] - [madek.app.server.export.meta-data-schema :as meta-data-schema] - [madek.app.server.state :as state] - [madek.app.server.utils :refer [deep-merge presence]] - - [json-roa.client.core :as roa] - [clj-time.core :as time] - - [cheshire.core :as cheshire] - [clojure.java.io :as io] - - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher :refer [snatch]] - [logbug.thrown :as thrown] - [logbug.debug :as debug :refer [identity-with-logging I> I>>]] - ) - - (:import - [java.io File] - [java.nio.file Files Paths])) - + [cheshire.core :as cheshire] + [clj-time.core :as time] + [clojure.java.io :as io] + [json-roa.client.core :as roa] + [logbug.catcher :as catcher :refer [snatch]] + [logbug.debug :as debug :refer [identity-with-logging I> I>>]] + [logbug.thrown :as thrown] + [madek.exporter.export.files :as files :refer [download-media-files path-prefix]] + [madek.exporter.export.index-html :as index-html] + [madek.exporter.export.meta-data :as meta-data :refer [meta-data write-meta-data]] + [madek.exporter.export.meta-data-schema :as meta-data-schema] + [madek.exporter.state :as state] + [madek.exporter.utils :refer [deep-merge presence]] + [taoensso.timbre :as logging :refer [debug]]) + + (:import + [java.io File] + [java.nio.file Files Paths])) ;### Path Helper ############################################################## @@ -32,21 +25,20 @@ (defn symlink [id source target] (snatch - {:level :debug - :throwable java.nio.file.FileAlreadyExistsException} - (swap! state/db - (fn [db id source target] - (deep-merge db {:download - {:items - {id - {:links - {source target}}}}})) - id source target) - (Files/createSymbolicLink - (nio-path source) - (nio-path target) - (make-array java.nio.file.attribute.FileAttribute 0)))) - + {:level :debug + :throwable java.nio.file.FileAlreadyExistsException} + (swap! state/db + (fn [db id source target] + (deep-merge db {:download + {:items + {id + {:links + {source target}}}}})) + id source target) + (Files/createSymbolicLink + (nio-path source) + (nio-path target) + (make-array java.nio.file.attribute.FileAttribute 0)))) ;### DL Media-Entry ########################################################### @@ -77,7 +69,7 @@ entry-dir-path (str dir-path File/separator entry-prefix-path) meta-data (meta-data media-entry)] (if (-> @state/db :download :items (get id)) - (let [target (-> @state/db :download :items (get id) :path)] + (let [target (-> @state/db :download :items (get id) :path)] (symlink id entry-dir-path target)) (do (swap! state/db (fn [db uuid media-entry] (assoc-in db [:download :items (str id)] media-entry)) @@ -97,15 +89,13 @@ (download-media-files entry-dir-path media-entry)) (set-item-to-finished id))))))) - ;### check credentials ######################################################## (defn check-credentials [api-entry-point api-http-opts] (let [response (-> (roa/get-root api-entry-point :default-conn-opts api-http-opts) (roa/relation :auth-info) (roa/get {}))] - (logging/debug (-> response roa/data)))) - + (debug (-> response roa/data)))) ;### DL Set ################################################################### @@ -132,29 +122,28 @@ (-> api-http-opts :cookies (get "madek-session"))) {:me_get_metadata_and_previews "true"} {:public_get_metadata_and_previews "true"})] - (doseq [collection (I>> identity-with-logging - (I> identity-with-logging - collection - (roa/relation :collections) - (roa/get coll-get-opts) - roa/coll-seq) - (map #(roa/get % {})))] + (doseq [collection (I>> identity-with-logging + (I> identity-with-logging + collection + (roa/relation :collections) + (roa/get coll-get-opts) + roa/coll-seq) + (map #(roa/get % {})))] (download-set - (-> collection roa/data :id) - target-dir-path recursive? skip-media-files? prefix-meta-key api-entry-point api-http-opts)))) - + (-> collection roa/data :id) + target-dir-path recursive? skip-media-files? prefix-meta-key api-entry-point api-http-opts)))) (defn download-set [id dl-path recursive? skip-media-files? prefix-meta-key api-entry-point api-http-opts] (let [collection (-> (roa/get-root api-entry-point :default-conn-opts api-http-opts) - (roa/relation :collection ) + (roa/relation :collection) (roa/get {:id id})) path-prefix (path-prefix prefix-meta-key collection) target-dir-path (str dl-path File/separator path-prefix) meta-data (meta-data collection)] (if (-> @state/db :download :items (get id)) - (let [target (-> @state/db :download :items (get id) :path)] + (let [target (-> @state/db :download :items (get id) :path)] (symlink id target-dir-path target)) (catcher/with-logging {} (swap! state/db (fn [db id] (deep-merge db {:download {:items {id {}}}})) id) @@ -173,14 +162,13 @@ (-> collection roa/data (assoc :type :collection)) path-prefix) (download-media-entries-for-set - id target-dir-path skip-media-files? prefix-meta-key api-entry-point api-http-opts) + id target-dir-path skip-media-files? prefix-meta-key api-entry-point api-http-opts) (when recursive? (download-collections-for-collection - collection target-dir-path recursive? skip-media-files? prefix-meta-key - api-entry-point api-http-opts)) + collection target-dir-path recursive? skip-media-files? prefix-meta-key + api-entry-point api-http-opts)) (set-item-to-finished id))))) - ;### download meta-data schema ################################################ (def download-meta-data-schema meta-data-schema/download) @@ -189,6 +177,6 @@ ;(logging-config/set-logger! :level :debug) ;(logging-config/set-logger! :level :info) ;(debug/debug-ns 'ring.middleware.resource) -;(debug/debug-ns *ns*) +(debug/debug-ns *ns*) ;(debug/debug-ns 'json-roa.client.core) ;(debug/debug-ns 'uritemplate-clj.core) diff --git a/jvm_main/src/madek/app/server/export/files.clj b/jvm_main/src/madek/exporter/export/files.clj similarity index 82% rename from jvm_main/src/madek/app/server/export/files.clj rename to jvm_main/src/madek/exporter/export/files.clj index 851aae0..6ce74cd 100644 --- a/jvm_main/src/madek/app/server/export/files.clj +++ b/jvm_main/src/madek/exporter/export/files.clj @@ -1,22 +1,17 @@ -(ns madek.app.server.export.files +(ns madek.exporter.export.files (:require - [madek.app.server.state :as state] - [madek.app.server.utils :refer [deep-merge presence]] - - [json-roa.client.core :as roa] - [cheshire.core :as cheshire] - [clojure.java.io :as io] - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - [logbug.debug :as debug :refer [identity-with-logging I> I>>]] - [logbug.thrown :as thrown] - ) + [cheshire.core :as cheshire] + [clojure.java.io :as io] + [clojure.tools.logging :as logging] + [json-roa.client.core :as roa] + [logbug.catcher :as catcher] + [logbug.debug :as debug :refer [identity-with-logging I> I>>]] + [logbug.thrown :as thrown] + [madek.exporter.state :as state] + [madek.exporter.utils :refer [deep-merge presence]]) (:import - [java.io File] - )) + [java.io File])) ;### title and prefix ######################################################### @@ -35,27 +30,25 @@ (defn path-prefix [prefix-meta-key media-resource] (let [prefix-part-one (if-not (presence prefix-meta-key) "" - (if-let [mk-value (get-prefix - prefix-meta-key media-resource)] - (str (useableFileName mk-value) "_") ""))] + (if-let [mk-value (get-prefix + prefix-meta-key media-resource)] + (str (useableFileName mk-value) "_") ""))] (str prefix-part-one (-> media-resource roa/data :id)))) - - ;### DL Previews ############################################################## (defn download-previews [target-dir media-file item-id media-file-id] (let [previews-dir (str target-dir File/separator "previews")] (doseq [preview-rel (-> media-file roa/coll-seq)] (let [preview (roa/get preview-rel {}) - preview-id (-> preview roa/data :id) + preview-id (-> preview roa/data :id) preview-path (str previews-dir File/separator (-> preview roa/data :filename)) preview-response (-> preview (roa/relation :data-stream) (roa/get {} :mod-conn-opts #(assoc % :as :stream)))] (swap! state/db - (fn [db params] + (fn [db params] (deep-merge db params)) {:download {:items @@ -67,8 +60,7 @@ {:path preview-path}}}}}}}}) (io/make-parents preview-path) (clojure.java.io/copy (-> preview-response :body) - (clojure.java.io/file preview-path)) - )))) + (clojure.java.io/file preview-path)))))) ;### DL Media-Files ########################################################### @@ -92,8 +84,7 @@ {:path file-path}}}}}}) (io/make-parents file-path) (clojure.java.io/copy (-> response :body) (clojure.java.io/file file-path)) - (download-previews target-dir media-file item-id media-file-id) - )) + (download-previews target-dir media-file item-id media-file-id))) (defn download-media-files [target-dir media-entry] (catcher/with-logging {} @@ -105,9 +96,7 @@ media-file-data-path (str media-file-dir File/separator "data.json")] (io/make-parents media-file-data-path) (spit media-file-data-path (cheshire/generate-string media-file-data {:pretty true})) - (download-media-file media-file-dir media-file item-id) - ))))) - + (download-media-file media-file-dir media-file item-id)))))) ;### Debug #################################################################### ;(logging-config/set-logger! :level :debug) diff --git a/jvm_main/src/madek/app/server/export/index_html.clj b/jvm_main/src/madek/exporter/export/index_html.clj similarity index 64% rename from jvm_main/src/madek/app/server/export/index_html.clj rename to jvm_main/src/madek/exporter/export/index_html.clj index 32aa7a3..be6e3d9 100644 --- a/jvm_main/src/madek/app/server/export/index_html.clj +++ b/jvm_main/src/madek/exporter/export/index_html.clj @@ -1,25 +1,20 @@ -(ns madek.app.server.export.index-html +(ns madek.exporter.export.index-html (:require - [madek.app.server.export.files :as files :refer [path-prefix]] - [madek.app.server.state :as state] - [madek.app.server.utils :refer [deep-merge]] - - [hiccup.core :as hiccup] - [hiccup.page :refer [html5]] - [json-roa.client.core :as roa] - [cheshire.core :as cheshire] - [clojure.java.io :as io] - [camel-snake-kebab.core :refer [->PascalCase]] - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - [logbug.thrown :as thrown] - [logbug.debug :as debug :refer [I> I>>]] - ) + [camel-snake-kebab.core :refer [->PascalCase]] + [cheshire.core :as cheshire] + [clojure.java.io :as io] + [hiccup.core :as hiccup] + [hiccup.page :refer [html5]] + [json-roa.client.core :as roa] + [logbug.catcher :as catcher] + [logbug.debug :as debug :refer [I> I>>]] + [logbug.thrown :as thrown] + [madek.exporter.export.files :as files :refer [path-prefix]] + [madek.exporter.state :as state] + [madek.exporter.utils :refer [deep-merge]]) (:import - [java.io File])) + [java.io File])) (defn meta-keys_unmemoized [] (->> (-> (roa/get-root (state/connection-entry-point) @@ -35,23 +30,22 @@ (def meta-keys (memoize meta-keys_unmemoized)) (defn title [media-resource] - (str (-> media-resource :type name ->PascalCase ) + (str (-> media-resource :type name ->PascalCase) " " (-> media-resource :id))) (defn url [media-resource] (let [url (str (-> @state/db :connection :url) (case (:type media-resource) - :media-entry "/entries/" - :collection "/sets/") + :media-entry "/entries/" + :collection "/sets/") (:id media-resource))] [:a {:href url} url])) (defn html-generic-meta-datum-value [meta-datum] - [:pre (cheshire/generate-string (or (:value meta-datum) (:values meta-datum)) {:pretty true})] - ) + [:pre (cheshire/generate-string (or (:value meta-datum) (:values meta-datum)) {:pretty true})]) (defn html-keywords-values [meta-datum] [:pre @@ -59,6 +53,10 @@ (map :term) (clojure.string/join ", "))]) +(defn html-generic [meta-datum] + [:pre + (cheshire/generate-string meta-datum {:pretty true})]) + (defn html-people-values [meta-datum] (-> (->> (:values meta-datum) (map #(dissoc % :date_of_birth :date_of_death :id))) @@ -70,8 +68,10 @@ [:h3 (or (:label (get (meta-keys) meta-key-id nil)) meta-key-id)] (case (:type meta-datum) "MetaDatum::Keywords" (html-keywords-values meta-datum) - ("MetaDatum::TextDate" "MetaDatum::Text") (:value meta-datum) - "MetaDatum::People" (html-people-values meta-datum))])) + "MetaDatum::People" (html-people-values meta-datum) + ("MetaDatum::Text" + "MetaDatum::TextDate") (:value meta-datum) + (html-generic meta-datum))])) (defn html-meta-data [meta-data] [:div.meta-data @@ -81,13 +81,13 @@ (defn html [media-resource meta-data] (html5 - [:head - [:title (title media-resource)] - [:meta {:charset "utf-8"}] - [:body - [:h2 (title media-resource)] - [:p "URL: " (url media-resource)] - (html-meta-data meta-data)]])) + [:head + [:title (title media-resource)] + [:meta {:charset "utf-8"}] + [:body + [:h2 (title media-resource)] + [:p "URL: " (url media-resource)] + (html-meta-data meta-data)]])) (defn write [target-dir meta-data media-resource prefix-path] (io/make-parents target-dir) diff --git a/jvm_main/src/madek/exporter/export/meta_data.clj b/jvm_main/src/madek/exporter/export/meta_data.clj new file mode 100644 index 0000000..7e72c62 --- /dev/null +++ b/jvm_main/src/madek/exporter/export/meta_data.clj @@ -0,0 +1,119 @@ +(ns madek.exporter.export.meta-data + (:require + [cheshire.core :as cheshire] + [clojure.java.io :as io] + [json-roa.client.core :as roa] + [logbug.catcher :as catcher] + [logbug.debug :as debug :refer [I> I>>]] + [logbug.thrown :as thrown] + [madek.exporter.state :as state] + [madek.exporter.utils :refer [deep-merge]] + [taoensso.timbre :as timbre :refer [info debug warn error spy]]) + (:import + [java.io File])) + +;### meta data ################################################################ + +(defn replace-person-id-with-person-data + "enrichtes the given data with person information iff it has a person_id key" + [{person-id :person_id :as data} roa-conn-opts] + (if-not person-id + data + (let [person (-> ; build some fake person-roa-data since this is missing as an relation + ; then use this to get the person data + {:name "Person" + :href (str "/api/people/" person-id) + :relations {} + :roa-conn-opts roa-conn-opts} + (roa/get {}) ; get it + roa/data + (select-keys [:external_uris + :first_name + :id + :institution + :institutional_id + :last_name + :pseudonym + :subtype]))] + (-> data + (dissoc :person_id) + (assoc :person person))))) + +(defn replace-role-id-with-role-data + "enrichtes the given data with role information iff it has a role_id key" + [{role-id :role_id :as data} roa-conn-opts] + (if-not role-id + data + (let [role (-> ; build some fake role-roa-data since this is missing as an relation + ; then use this to get the role data + {:name "Role" + :href (str "/api/roles/" role-id) + :relations {} + :roa-conn-opts roa-conn-opts} + (roa/get {}) ; get it + roa/data + (select-keys [:id + :labels]))] + (-> data + (dissoc :role_id) + (assoc :role role))))) + +(defn get-meta-data-for-md-relation-type [md] + (-> md + (roa/get {}) + roa/data + (replace-person-id-with-person-data (:roa-conn-opts md)) + (replace-role-id-with-role-data (:roa-conn-opts md)))) + +(defn get-collection-meta-datum-values [meta-datum] + (merge (-> meta-datum roa/data + (dissoc :value)) + {:values (->> meta-datum + roa/coll-seq + (map get-meta-data-for-md-relation-type))})) + +(defn get-scalar-meta-datum-value [meta-datum] + (-> meta-datum + roa/data)) + +(defn meta-data_unmemoized [media-resource] + (->> (-> media-resource + (roa/relation :meta-data) + (roa/get {}) + roa/coll-seq) + (map #(roa/get % {})) + (map (fn [meta-datum] + (case (-> meta-datum roa/data :type) + ("MetaDatum::Text" "MetaDatum::TextDate") (get-scalar-meta-datum-value meta-datum) + (get-collection-meta-datum-values meta-datum)))))) + +(def meta-data (memoize meta-data_unmemoized)) + +(defn title [meta-data] + (:value (some (fn [meta-datum] + (and (= "madek_core:title" (:meta_key_id meta-datum)) + meta-datum)) + meta-data))) + +(defn write-meta-data [target-dir meta-data item-id prefix-path] + (let [content (cheshire/generate-string meta-data {:pretty true})] + (doseq [path [(str target-dir File/separator "meta-data.json") + (str target-dir File/separator prefix-path "_meta-data.json")]] + (io/make-parents path) + (spit path content) + (swap! state/db + (fn [db params] + (deep-merge db params)) + {:download + {:items + {item-id + {:title (title meta-data) + :meta-data + {:path path + :data meta-data}}}}})))) + +;### Debug #################################################################### +;(logging-config/set-logger! :level :debug) +;(logging-config/set-logger! :level :info) +;(debug/debug-ns 'ring.middleware.resource) +;(debug/debug-ns *ns*) diff --git a/jvm_main/src/madek/app/server/export/meta_data_schema.clj b/jvm_main/src/madek/exporter/export/meta_data_schema.clj similarity index 72% rename from jvm_main/src/madek/app/server/export/meta_data_schema.clj rename to jvm_main/src/madek/exporter/export/meta_data_schema.clj index 079ea96..e7c52ea 100644 --- a/jvm_main/src/madek/app/server/export/meta_data_schema.clj +++ b/jvm_main/src/madek/exporter/export/meta_data_schema.clj @@ -1,22 +1,16 @@ -(ns madek.app.server.export.meta-data-schema +(ns madek.exporter.export.meta-data-schema (:require - [madek.app.server.state :as state] - [json-roa.client.core :as roa] - [madek.app.server.utils :refer [deep-merge]] - - [cheshire.core :as cheshire] - [clojure.java.io :as io] - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - [logbug.thrown :as thrown] - [logbug.debug :as debug :refer [I> I>>]] - ) + [cheshire.core :as cheshire] + [clojure.java.io :as io] + [json-roa.client.core :as roa] + [logbug.catcher :as catcher] + [logbug.debug :as debug :refer [I> I>>]] + [logbug.thrown :as thrown] + [madek.exporter.state :as state] + [madek.exporter.utils :refer [deep-merge]]) (:import - [java.io File] - )) + [java.io File])) (defn meta-keys [vocabulary] (->> (-> vocabulary @@ -50,7 +44,6 @@ (io/make-parents path) (spit path (cheshire/generate-string schema {:pretty true})))) - ;### Debug #################################################################### ;(debug/re-apply-last-argument #'meta-data-schema_unmemoized) ;(debug/re-apply-last-argument #'download) diff --git a/jvm_main/src/madek/exporter/logging.clj b/jvm_main/src/madek/exporter/logging.clj new file mode 100644 index 0000000..6881b58 --- /dev/null +++ b/jvm_main/src/madek/exporter/logging.clj @@ -0,0 +1,20 @@ +(ns madek.exporter.logging + (:require + [taoensso.timbre :as timbre :refer [debug info]] + [taoensso.timbre.tools.logging])) + +(def DEFAULT_LOGGING_CONFIG + {:min-level [[#{;"madek.exporter.server.*" + "madek.exporter.export.*" + ;"madek.exporter.connection" + ;"madek.exporter.export.*" + }:debug] + [#{"madek.exporter.*"} :info] + [#{"*"} :warn]] + :log-level nil}) + +(defn init [] + (info "initializing logging" DEFAULT_LOGGING_CONFIG) + (timbre/merge-config! DEFAULT_LOGGING_CONFIG) + (taoensso.timbre.tools.logging/use-timbre) + (info "initialized logging" (pr-str timbre/*config*))) diff --git a/jvm_main/src/madek/exporter/main.clj b/jvm_main/src/madek/exporter/main.clj new file mode 100644 index 0000000..2eaf69e --- /dev/null +++ b/jvm_main/src/madek/exporter/main.clj @@ -0,0 +1,58 @@ +(ns madek.exporter.main + (:gen-class) + (:require + [clojure.pprint :refer [pprint]] + [clojure.string] + [clojure.tools.cli :as cli] + [madek.exporter.cli-run :as cli-run] + [madek.exporter.logging :as logging] + [madek.exporter.repl :as repl] + [madek.exporter.server.main :as server] + [taoensso.timbre :as timbre :refer [info debug warn error]])) + +(def cli-options + (concat + [["-h" "--help"]] + repl/cli-options)) + +(defn main-usage [options-summary & more] + (->> ["Usage: madek-exporter SCORE " + "scopes: server, cli" + "" + options-summary + "" + "" + (when more + ["-------------------------------------------------------------------" + (with-out-str (pprint more)) + "-------------------------------------------------------------------"])] + flatten + (clojure.string/join \newline))) + +(defn main [args] + (try + (logging/init) + (let [{:keys [options arguments errors summary]} + (cli/parse-opts args cli-options :in-order true) + cmd (some-> arguments first keyword) + pass-on-args (->> (rest arguments) flatten (into [])) + options (into (sorted-map) options) + print-summary #(println (main-usage summary {:args args :options options}))] + (info {'args args 'options options 'cmd cmd 'pass-on-args pass-on-args}) + (repl/init options) + (cond + (:help options) (print-summary) + :else (case cmd + :server (server/main options pass-on-args) + :cli (cli-run/main options pass-on-args) + (print-summary)))) + (catch Exception ex + (error ex)))) + +(defonce args* (atom nil)) +(when @args* (main @args*)) + +(defn -main [& args] + (reset! args* args) + (main args)) + diff --git a/jvm_main/src/madek/exporter/repl.clj b/jvm_main/src/madek/exporter/repl.clj new file mode 100644 index 0000000..69adf29 --- /dev/null +++ b/jvm_main/src/madek/exporter/repl.clj @@ -0,0 +1,66 @@ +(ns madek.exporter.repl + (:require + ;[clojure.core :refer [boolean?]] + [clj-yaml.core :as yaml] + [clojure.java.io :as io] + [cuerdas.core :as string :refer [snake kebab upper human]] + [environ.core :refer [env]] + [nrepl.server :as nrepl-server :refer [start-server stop-server]] + [taoensso.timbre :refer [debug error info spy warn]])) + +(defn long-opt-for-key [k] + (str "--" (kebab k) " " (-> k snake upper))) + +;;; cli-options ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defonce options* (atom nil)) + +(def repl-enable-key :repl) +(def repl-port-key :repl-port) +(def repl-bind-key :repl-bind) +(def repl-port-file-key :repl-port-file) +(def options-keys [repl-enable-key repl-bind-key repl-port-key repl-port-file-key]) + +(def cli-options + [["-r" (long-opt-for-key repl-enable-key) "start the nREPL server" + :default (or (some-> repl-enable-key env yaml/parse-string) false) + :parse-fn #(yaml/parse-string %) + ;:validate [boolean? "Must parse to a boolean"] + ] + [nil (long-opt-for-key repl-port-key) "nREPL port (random default)" + :default (or (some-> repl-port-key env Integer/parseInt) + (+ 10000 (rand-int (- 65536 10000)))) + :parse-fn #(Integer/parseInt %) + :validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]] + [nil (long-opt-for-key repl-bind-key) "nREPL bind interface" + :default (or (some-> repl-bind-key env) "localhost")] + [nil (long-opt-for-key repl-port-file-key) "write port to this file; NO (or any YAML falsy) disables this" + :default (or (some-> repl-port-file-key env yaml/parse-string) ".nrepl-port")]]) + +;;; server ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defonce server* (atom nil)) + +(defn stop [] + (when @server* + (info "stopping nREPL server " @server*) + (stop-server @server*) + (when-let [port-file (repl-port-file-key @options*)] + (io/delete-file port-file true)) + (reset! server* nil) + (reset! options* nil))) + +(defn init [options] + (info 'init options) + (if @server* + (info "repl server ist already running, ignoring init") + (do (reset! options* (select-keys options options-keys)) + (stop) + (when (repl-enable-key @options*) + (let [bind (repl-bind-key @options*) + port (repl-port-key @options*)] + (info "starting nREPL server " port bind) + (reset! server* (start-server :bind bind :port port)) + (when-let [port-file (repl-port-file-key @options*)] + (spit port-file (str port)) + (info "started nREPL server "))))))) diff --git a/jvm_main/src/madek/exporter/scratch.clj b/jvm_main/src/madek/exporter/scratch.clj new file mode 100644 index 0000000..c0c433b --- /dev/null +++ b/jvm_main/src/madek/exporter/scratch.clj @@ -0,0 +1,5 @@ +(ns madek.exporter.scratch + (:require + [clojure.data :refer :all] + [timothypratley.patchin :as patchin])) + diff --git a/jvm_main/src/madek/app/server/server.clj b/jvm_main/src/madek/exporter/server/http_server.clj similarity index 78% rename from jvm_main/src/madek/app/server/server.clj rename to jvm_main/src/madek/exporter/server/http_server.clj index 8196221..d54cf0f 100644 --- a/jvm_main/src/madek/app/server/server.clj +++ b/jvm_main/src/madek/exporter/server/http_server.clj @@ -1,27 +1,17 @@ -(ns madek.app.server.server +(ns madek.exporter.server.http-server (:require - [madek.app.server.web :as web] - [madek.app.server.utils :as utils :refer [presence]] - - [clojure.data.codec.base64 :as base64] - [environ.core :refer [env]] - ;[ring.adapter.jetty :refer [run-jetty]] - ;[ring.adapter.undertow :refer [run-undertow]] - [immutant.web :refer [run]] - [clojure.walk] - - [logbug.catcher :as catcher] - [logbug.thrown] - [clojure.tools.logging :as logging] - - [logbug.catcher :as catcher] - [logbug.thrown] - [logbug.debug :as debug :refer [ I> ]] - [logbug.ring :as logbug-ring :refer [wrap-handler-with-logging]] - - ) - (:gen-class)) - + [clojure.data.codec.base64 :as base64] + [clojure.tools.logging :as logging] + [clojure.walk] + [environ.core :refer [env]] + [immutant.web :refer [run]] + [logbug.catcher :as catcher] + [logbug.catcher :as catcher] + [logbug.debug :as debug :refer [I>]] + [logbug.ring :as logbug-ring :refer [wrap-handler-with-logging]] + [logbug.thrown] + [madek.exporter.server.web :as web] + [madek.exporter.utils :as utils :refer [presence]])) (def web-server (atom nil)) @@ -55,7 +45,6 @@ (fn [request] (http-basic-authorize request handler password))) - ;;; Initialize ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn initialize [server-config app-config] @@ -77,8 +66,6 @@ (utils/exit 0)) (throw e)))))) - - ;### Debug #################################################################### ;(logging-config/set-logger! :level :debug) ;(logging-config/set-logger! :level :info) diff --git a/jvm_main/src/madek/app/server/main.clj b/jvm_main/src/madek/exporter/server/main.clj similarity index 51% rename from jvm_main/src/madek/app/server/main.clj rename to jvm_main/src/madek/exporter/server/main.clj index 48a9c50..42a0f6c 100644 --- a/jvm_main/src/madek/app/server/main.clj +++ b/jvm_main/src/madek/exporter/server/main.clj @@ -1,20 +1,15 @@ -(ns madek.app.server.main +(ns madek.exporter.server.main (:gen-class) (:require - [madek.app.server.server :as server] - [madek.app.server.state :as state] - [madek.app.server.utils :as utils :refer [exit presence]] - - - [environ.core :refer [env]] - [clojure.pprint :refer [pprint]] - [clojure.string :as string] - [clojure.tools.cli :refer [parse-opts]] - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - )) + [clojure.pprint :refer [pprint]] + [clojure.string :as string] + [clojure.tools.cli :refer [parse-opts]] + [environ.core :refer [env]] + [logbug.catcher :as catcher] + [logbug.thrown] + [madek.exporter.server.http-server :as server] + [madek.exporter.state :as state] + [madek.exporter.utils :as utils :refer [exit presence]])) (def cli-options [["-u" "--madek-url URL" "Madek URL" @@ -35,7 +30,7 @@ ["-h" "--help"]]) (defn usage [options-summary & more] - (->> ["Madek-Exporter" + (->> ["Madek-Exporter Server" "" "Options:" options-summary @@ -47,30 +42,29 @@ "-------------------------------------------------------------------"])] flatten (string/join \newline))) -(defn -main [& args] +(defn main [global-opts args] (logbug.thrown/reset-ns-filter-regex #".*madek.*") (catcher/snatch - {:level :fatal - :throwable Throwable - :return-fn (fn [_] (System/exit -1))} - (let [{:keys [options arguments errors summary]} - (parse-opts args cli-options)] - (cond - (:help options) (exit 0 (usage summary {:options options}))) - (println (usage summary {:options options})) - (let [{target-dir :download-dir madke-url :madek-url} options] - (state/initialize - {:jvm-main-options options - :download-parameters - {:target-dir target-dir } - :connection - {:madek-url madke-url}})) - (let[{port :port host :interface password :password} options] - (server/initialize - {:port port - :host host} - {:password password}))))) - + {:level :fatal + :throwable Throwable + :return-fn (fn [_] (System/exit -1))} + (let [{:keys [options arguments errors summary]} + (parse-opts args cli-options)] + (cond + (:help options) (exit 0 (usage summary {:options options}))) + (println (usage summary {:options options})) + (let [{target-dir :download-dir madek-url :madek-url} options] + (state/initialize + {:jvm-main-options options + :download-parameters + {:target-dir target-dir} + :connection + {:madek-url madek-url}})) + (let [{port :port host :interface password :password} options] + (server/initialize + {:port port + :host host} + {:password password}))))) ;(-> (Desktop/getDesktop)(.browse (URI. "file:///Users/Thomas"))) ;(sh "open" "http://localhost:3000") diff --git a/jvm_main/src/madek/exporter/server/web.clj b/jvm_main/src/madek/exporter/server/web.clj new file mode 100644 index 0000000..659158f --- /dev/null +++ b/jvm_main/src/madek/exporter/server/web.clj @@ -0,0 +1,261 @@ +(ns madek.exporter.server.web + (:refer-clojure :exclude [str keyword]) + + (:require + + [cheshire.core :as cheshire] + [clj-http.client :as http-client] + [clj-logging-config.log4j :as logging-config] + [clojure.data.json :as json] + + [clojure.pprint :refer [pprint]] + [clojure.tools.logging :as logging] + [compojure.core :refer [ANY GET PATCH POST DELETE defroutes]] + [compojure.route :refer [not-found resources]] + [environ.core :refer [env]] + [hiccup.core :refer [html]] + [hiccup.page :refer [include-js include-css]] + [inflections.core :refer [capitalize]] + [json-roa.client.core :as roa] + [logbug.catcher :as catcher] + [logbug.debug :as debug :refer [I> I>>]] + [logbug.ring :as logbug-ring :refer [wrap-handler-with-logging]] + [logbug.thrown :as thrown] + [madek.exporter.connection :as connection] + + [madek.exporter.export :as export] + [madek.exporter.state :as state] + [madek.exporter.utils :as utils :refer [str keyword deep-merge presence]] + [ring.middleware.defaults :refer [site-defaults wrap-defaults]] + [ring.middleware.json] + [ring.util.response :refer [response]])) + +;### download entity ########################################################## + +(defn download-step1 [request] + (catcher/snatch + {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} + (let [http-options (-> @state/db :connection :http-options) + id (-> request :body :entity-id) + entity-type (case (-> request :body :entity-type) + "entry" :media-entry + "set" :collection) + entity (-> (roa/get-root (str (-> @state/db :connection :url) "/api") + :default-conn-opts (-> @state/db :connection :http-options)) + (roa/relation entity-type) + (roa/get {:id id})) + title (-> entity + (roa/relation :meta-data) + (roa/get {:meta_keys (json/write-str ["madek_core:title"])}) + roa/coll-seq first (roa/get {}) roa/data :value)] + (do (swap! state/db + (fn [db dl-entity target-dir] + (deep-merge db + {:download + {:step1-completed true + :entity dl-entity + :target-directory target-dir}})) + {:title title + :uuid id + :type entity-type + :url (-> request :body :url)} + (-> request :body :target-directory)) + {:status 204})))) + +;(pprint @state/db) + +;### set options ############################################################## + +(defn patch-download [request] + (catcher/snatch + {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} + (swap! state/db + (fn [db body] + (assoc-in db [:download] + (deep-merge (:download db) + body))) + (:body request)) + {:status 204})) + +;############################################################################## + +(defonce download-future (atom nil)) + +(def snatch-dl-exception-params + {:return-fn (fn [e] + (swap! state/db + (fn [db e] + (deep-merge db + {:download + {:state :failed + :errors {:dowload-error (str e)}}})) + e)) + :throwable Throwable}) + +(defn start-download-future [id target-dir recursive? skip-media-files? prefix-meta-key entry-point http-options] + (reset! download-future + (future + (catcher/snatch + {:return-fn (fn [e] + (swap! state/db + (fn [db e] + (deep-merge db + {:download + {:download-finished true + :errors {:dowload-error (str e)}}})) + e)) + :throwable Throwable} + (case (-> @state/db :download :entity :type) + :collection (export/download-set + id target-dir recursive? skip-media-files? + prefix-meta-key entry-point http-options) + :media-entry (export/download-media-entry + id target-dir skip-media-files? prefix-meta-key + entry-point http-options)) + (swap! state/db (fn [db] (assoc-in db [:download :download-finished] true))))))) + +(defn download [request] + (if (and @download-future (not (realized? @download-future))) + {:status 422 :body "There seems to be an ongoing download in progress!"} + (catcher/snatch + {:return-fn (fn [e] + (swap! state/db + (fn [db e] + (deep-merge db + {:download + {:download-finished true + :errors {:dowload-error (str e)}}})) + e)) + :throwable Throwable} + (swap! state/db (fn [db] (assoc-in db [:download :download-started] true))) + (let [id (-> @state/db :download :entity :uuid) + target-dir (-> @state/db :download :target-directory) + recursive? (-> @state/db :download :recursive not not) + skip-media-files? (-> @state/db :download :skip_media_files not not) + download-meta-data-schema? true + prefix-meta-key (-> @state/db :download :prefix_meta_key presence) + entry-point (state/connection-entry-point) + http-options (state/connection-http-options)] + (when download-meta-data-schema? + (export/download-meta-data-schema target-dir)) + (start-download-future id target-dir recursive? skip-media-files? prefix-meta-key entry-point http-options)) + {:status 202}))) + +(defn patch-download-item [request] + (logging/debug 'patch-download-item {:request request}) + (let [item-id (-> request :route-params :id) + patch-params (-> request :body)] + (swap! state/db + (fn [db item-id patch-params] + (let [item-params (or (-> db :download :items (get item-id)) {})] + (assoc-in db [:download :items item-id] + (deep-merge item-params + patch-params)))) + item-id patch-params)) + {:status 204}) + +(defn delete-download [_] + (swap! state/db (fn [db] + (dissoc db :download :download-entity))) + {:status 204}) + +;############################################################################## + +(defn patch-download-parameters [request] + (logging/debug 'patch-download-parameters {:request request}) + (swap! state/db + (fn [db params] + (deep-merge db + {:download-parameters params})) + (:body request)) + {:status 204}) + +;############################################################################## + +(defn open [request] + (logging/debug request) + (utils/os-browse (-> request :body :uri)) + {:status 201}) + +;############################################################################## + +(defn shutdown [request] + (future + (Thread/sleep 3000) + (System/exit 0)) + "Good Bye!") + +;############################################################################## + +(defn vocabularies [_] + (catcher/snatch + {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} + (let [http-options (-> @state/db :connection :http-options) + vocabularies (->> (-> (roa/get-root (str (-> @state/db :connection :url) "/api") + :default-conn-opts (-> @state/db :connection :http-options)) + (roa/relation :vocabularies) + (roa/get {}) + roa/coll-seq) + (map #(roa/get % {})) + (map roa/data))] + (response vocabularies)))) + +(defn meta-keys [vocabulary] + (catcher/snatch + {:return-fn (fn [e] {:status 500 :body (thrown/stringify e)})} + (let [http-options (-> @state/db :connection :http-options) + meta-keys (->> (-> (roa/get-root (str (-> @state/db :connection :url) "/api") + :default-conn-opts (-> @state/db :connection :http-options)) + (roa/relation :meta-keys) + (roa/get {:vocabulary vocabulary}) + roa/coll-seq) + (map #(roa/get % {})) + (map roa/data))] + (response meta-keys)))) + +;############################################################################## + +(defroutes routes + + (DELETE "/download" _ #'delete-download) + + (POST "/connect" _ #'connection/connect-to-madek-server) + (DELETE "/connect" _ #'connection/disconnect) + + (POST "/open" _ #'open) + + (PATCH "/download" _ #'patch-download) + + (PATCH "/download/items/:id" _ #'patch-download-item) + + (PATCH "/download-parameters" _ #'patch-download-parameters) + + (POST "/download" _ #'download) + + (POST "/download/step1" _ #'download-step1) + + (ANY "/shutdown" _ #'shutdown) + + (GET "/vocabularies/" _ #'vocabularies) + (GET "/vocabularies/:vocabulary/meta-keys/" + [vocabulary] (#'meta-keys vocabulary)) + + (resources "/") + + (not-found "Not Found")) + +(def app + (I> wrap-handler-with-logging + routes + state/wrap + ring.middleware.json/wrap-json-response + (wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false)) + (ring.middleware.json/wrap-json-body {:keywords? true}) + ring.middleware.keyword-params/wrap-keyword-params + ring.middleware.params/wrap-params)) + +;### Debug #################################################################### +;(logging-config/set-logger! :level :debug) +;(logging-config/set-logger! :level :info) +;(debug/debug-ns 'ring.middleware.resource) +;(debug/debug-ns *ns*) diff --git a/jvm_main/src/madek/app/server/state.clj b/jvm_main/src/madek/exporter/state.clj similarity index 70% rename from jvm_main/src/madek/app/server/state.clj rename to jvm_main/src/madek/exporter/state.clj index e7cdd31..8c42141 100644 --- a/jvm_main/src/madek/app/server/state.clj +++ b/jvm_main/src/madek/exporter/state.clj @@ -1,36 +1,33 @@ -(ns madek.app.server.state +(ns madek.exporter.state (:require - [madek.app.server.utils :as utils :refer [exit presence deep-merge]] - - [clojure.set :refer [difference]] - [compojure.core :as cpj] - [taoensso.sente :as sente] - [taoensso.sente.server-adapters.immutant :refer [sente-web-server-adapter]] - [timothypratley.patchin :as patchin] - - [clojure.java.io :as io] - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - [logbug.thrown] - [logbug.debug :as debug :refer [ I> ]] - [logbug.ring :as logbug-ring :refer [wrap-handler-with-logging]] - - )) - + [clojure.java.io :as io] + [clojure.set :refer [difference]] + [compojure.core :as cpj] + [logbug.catcher :as catcher] + [logbug.debug :as debug :refer [I>]] + [logbug.ring :as logbug-ring :refer [wrap-handler-with-logging]] + [logbug.thrown] + [madek.exporter.utils :as utils :refer [exit presence deep-merge]] + [taoensso.sente :as sente] + [taoensso.sente.server-adapters.immutant :refer [sente-web-server-adapter]] + [taoensso.timbre :refer [info debug warn]] + [timothypratley.patchin :as patchin])) ;### THE DATABASE ############################################################# (def default-download-directory (clojure.string/join java.io.File/separator - [(System/getProperty "user.home") - "Downloads" "Madek-Export"])) + [(System/getProperty "user.home") + "Downloads" "Madek-Export"])) (defonce db (atom {:download {:target-directory default-download-directory}})) ;(reset! db {:download {:target-directory default-download-directory}}) (swap! db assoc-in [:download :state] :step1) +(comment + (:connection @db)) + (defonce clients (atom {})) ;### connection params ######################################################## @@ -52,28 +49,25 @@ (let [{:keys [ch-recv send-fn ajax-post-fn ajax-get-or-ws-handshake-fn connected-uids]} (sente/make-channel-socket! - sente-web-server-adapter - {:user-id-fn (fn [req] (:client-id req))})] + sente-web-server-adapter + {:user-id-fn (fn [req] (:client-id req))})] (def ring-ajax-post ajax-post-fn) (def ring-ajax-get-or-ws-handshake ajax-get-or-ws-handshake-fn) (def ch-chsk ch-recv) ; ChannelSocket's receive channel (def chsk-send! send-fn) ; ChannelSocket's send API fn (def connected-uids connected-uids) ; Watchable, read-only atom) )) - - (defn ^:private routes [default-handler] (cpj/routes - (cpj/GET "/chsk" req (ring-ajax-get-or-ws-handshake req)) - (cpj/POST "/chsk" req (ring-ajax-post req)) - (cpj/ANY "*" _ default-handler))) + (cpj/GET "/chsk" req (ring-ajax-get-or-ws-handshake req)) + (cpj/POST "/chsk" req (ring-ajax-post req)) + (cpj/ANY "*" _ default-handler))) (defn wrap [handler] (I> (wrap-handler-with-logging :trace) handler routes)) - ;### publish database ######################################################### (defonce last-client-pushes (atom {})) @@ -106,37 +100,36 @@ (doseq [client (keys @clients)] (publish client "db" new-state))) - ;### manage clients ########################################################### (defn watch-connected-uids [_ _ old-state new-state] (let [current-clients (-> new-state :any) removed-clients (difference (-> @clients keys set) current-clients) added-clients (difference current-clients (-> @clients keys set))] - (logging/debug {:current-clients current-clients - :removed-clients removed-clients - :added-clients added-clients}) + (debug {:current-clients current-clients + :removed-clients removed-clients + :added-clients added-clients}) (doseq [removed-client removed-clients] (swap! clients (fn [cls cid] (dissoc cls cid)) removed-client)) (doseq [added-client added-clients] (swap! clients (fn [cls cid] (assoc cls cid {})) added-client) (publish added-client "db" @db)))) - ;### initialize ############################################################### -(defn initialize [initial-db] - (swap! db deep-merge initial-db) - (initialize-sente) - (add-watch connected-uids :connected-uids #'watch-connected-uids) - (add-watch db :db #'watch-db) - (logging/info "initialized state" {:db @db})) +(defonce initialized* (atom false)) +(defn initialize [initial-db] + (if @initialized* + (warn "skipping db reinitialization") + (do (swap! db deep-merge initial-db) + (initialize-sente) + (add-watch connected-uids :connected-uids #'watch-connected-uids) + (add-watch db :db #'watch-db) + (info "initialized state" {:db @db}) + (reset! initialized* true)))) ;### Debug #################################################################### -;(logging-config/set-logger! :level :debug) -;(logging-config/set-logger! :level :info) ;(debug/debug-ns 'ring.middleware.resource) -;(logging-config/set-logger! :name "logbug.debug" :level :debug) ;(debug/debug-ns *ns*) diff --git a/jvm_main/src/madek/app/server/utils.clj b/jvm_main/src/madek/exporter/utils.clj similarity index 78% rename from jvm_main/src/madek/app/server/utils.clj rename to jvm_main/src/madek/exporter/utils.clj index 5f24467..1b67e2c 100644 --- a/jvm_main/src/madek/app/server/utils.clj +++ b/jvm_main/src/madek/exporter/utils.clj @@ -1,21 +1,16 @@ -(ns madek.app.server.utils +(ns madek.exporter.utils (:refer-clojure :exclude [str keyword]) (:require - [json-roa.client.core :as roa] - [clojure.string :as string] - [clojure.java.shell :refer [sh]] - - [clj-logging-config.log4j :as logging-config] - [clojure.tools.logging :as logging] - [logbug.catcher :as catcher] - [logbug.debug :as debug] - [logbug.thrown :as thrown] - ) + [clojure.java.shell :refer [sh]] + [clojure.string :as string] + [json-roa.client.core :as roa] + [logbug.catcher :as catcher] + [logbug.debug :as debug] + [logbug.thrown :as thrown]) (:import - [org.apache.commons.lang3 SystemUtils] - [java.awt Desktop] - [java.net URI] - )) + [java.awt Desktop] + [java.net URI] + [org.apache.commons.lang3 SystemUtils])) (defn deep-merge [& vals] (if (every? map? vals) @@ -53,7 +48,7 @@ (subs (clojure.core/str x) 1) (clojure.core/str x))) ([x & yx] - (apply clojure.core/str (concat [(str x)] (apply str yx))))) + (apply clojure.core/str (concat [(str x)] (apply str yx))))) (defn keyword "Like clojure.core/keyword but coerces an unknown single argument x diff --git a/log/.gitkeep b/log/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/logs/.gitkeep b/logs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/project.clj b/project.clj index 6a00b7c..abe661c 100644 --- a/project.clj +++ b/project.clj @@ -1,9 +1,11 @@ -(defproject madek "0.4.0" +(defproject madek "0.9.8" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "GPL" :url "https://de.wikipedia.org/wiki/GNU_General_Public_License"} - :dependencies [ + :dependencies [; enforce higher encore version: current timbre needs an newer + ; encore than sente + [com.taoensso/encore "3.79.0"] [camel-snake-kebab "0.4.0"] [cljs-http "0.1.43"] @@ -16,7 +18,6 @@ [hiccup "1.0.5"] [inflections "0.13.0"] [json-roa_clj-client "0.2.1"] - [log4j/log4j "1.2.17" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]] [logbug "4.2.2"] [org.apache.commons/commons-lang3 "3.5"] [org.clojure/clojure "1.8.0"] @@ -33,26 +34,31 @@ [ring/ring-json "0.4.0"] [secretary "1.2.3"] [timothypratley/patchin "0.3.5"] + [com.taoensso/timbre "6.3.1"] + + ; added for nrepl + [funcool/cuerdas "2023.11.09-407"] + [nrepl "1.1.1"] + [clj-yaml "0.4.0"] + ;[clj-commons/clj-yaml "1.0.27"] [venantius/accountant "0.2.0" :exclusions [org.clojure/tools.reader]] ; DON'T REMOVE THIS the clojurescript stuff depends on this version ; check and upgrade it when updating clojurescript [com.google.guava/guava "21.0"] + [javax.xml.bind/jaxb-api "2.3.1"] ] - ; jdk 9 needs ["--add-modules" "java.xml.bind"] - :jvm-opts #=(eval (if (re-matches #"^(9|10)\..*" (System/getProperty "java.version")) - ["--add-modules" "java.xml.bind"] - [])) + ;jdk since 9 needs ["--add-modules" "java.xml.bind"] + ;:jvm-opts ["--add-modules" "java.xml.bind"] - :plugins [ + :plugins [[lein-cljfmt "0.9.2"] [lein-cljsbuild "1.1.5"] [lein-environ "1.0.2"] [lein-externs "0.1.6"] [lein-libdir "0.1.1"] - [lein-shell "0.5.0"] - ] + [lein-shell "0.5.0"]] :source-paths ["jvm_main/src"] @@ -60,24 +66,22 @@ :env {:dev true} :plugins [[lein-figwheel "0.5.10" :exclusions [org.clojure/core.cache]] [lein-sassy "1.0.7"]] - :repl-options {:init-ns madek.app.server.main} + :repl-options {:init-ns madek.exporter.main} + :main madek.exporter.main :source-paths ["jvm_main/src", "electron_front/src/dev"] - :resource-paths["jvm_main/resources/dev"] - } + :resource-paths ["jvm_main/resources/dev"]} :prod {} - :uberjar { - :prep-tasks ["compile"] + :uberjar {:prep-tasks ["compile"] :source-paths ["jvm_main/src"] - :resource-paths["jvm_main/resources/prod"] + :resource-paths ["jvm_main/resources/prod"] :env {:production true} :uberjar-name "../app/prod/jvm-main.jar" - :aot [madek.app.server.main] + :aot [madek.exporter.main] :jar true - :main madek.app.server.main - } - } + :main madek.exporter.main}} + :aliases {"descjop-help" ["new" "descjop" "help"] "descjop-version" ["new" "descjop" "version"] "descjop-init" ["do" @@ -103,84 +107,84 @@ "descjop-uberapp-app-store" ["shell" "cmd.exe" "/c" "electron-packager" "./app/prod" "madek-exporter" "--platform=mas" "--arch=x64" "--electron-version=1.6.0"] "descjop-uberapp-linux" ["shell" "cmd.exe" "/c" "electron-packager" "./app/prod" "madek-exporter" "--platform=linux" "--arch=x64" "--electron-version=1.6.0"] "descjop-uberapp-win64" ["shell" "electron-packager" "./app/prod" "madek-exporter" "--platform=win32" "--arch=x64" "--electron-version=1.6.0"] - "descjop-uberapp-win32" ["shell" "cmd.exe" "/c" "electron-packager" "./app/prod" "madek-exporter" "--platform=win32" "--arch=ia32" "--electron-version=1.6.0"] - } + "descjop-uberapp-win32" ["shell" "cmd.exe" "/c" "electron-packager" "./app/prod" "madek-exporter" "--platform=win32" "--arch=ia32" "--electron-version=1.6.0"]} ;:hooks [leiningen.cljsbuild] -:cljsbuild {:builds - {:electron-main-dev - {:source-paths ["electron_main/src/all" "electron_main/src/dev"] - :incremental true - :jar true - :assert true - :compiler {:output-to "app/dev/js/main.js" - :externs ["app/dev/js/main_externs.js" - "node_modules/closurecompiler-externs/path.js" - "node_modules/closurecompiler-externs/process.js" - "js-yaml_externs.js"] - :warnings true - :elide-asserts true - :target :nodejs - :output-dir "app/dev/js/out_main" - :source-map true - :optimizations :none - :main "madek.app.main.main" - :pretty-print true - :output-wrapper true}} - :electron-main-prod - {:source-paths ["electron_main/src/all" "electron_main/src/prod"] - :incremental true - :jar true - :assert true - :compiler {:output-to "app/prod/js/main.js" - :externs ["app/prod/js/main_externs.js" - "node_modules/closurecompiler-externs/path.js" - "node_modules/closurecompiler-externs/process.js"] - :warnings true - :elide-asserts true - :target :nodejs - :output-dir "app/prod/js/out_main" - :optimizations :advanced - :source-map "app/prod/js/main.js.map" - :pretty-print true - :output-wrapper true}} - :electron-front-dev - {:source-paths ["electron_front/src/all" "electron_front/src/dev"] - :incremental true + :cljfmt {:remove-multiple-non-indenting-spaces? true + :sort-ns-references? true} + + :cljsbuild {:builds + {:electron-main-dev + {:source-paths ["electron_main/src/all" "electron_main/src/dev"] + :incremental true + :jar true + :assert true + :compiler {:output-to "app/dev/js/main.js" + :externs ["app/dev/js/main_externs.js" + "node_modules/closurecompiler-externs/path.js" + "node_modules/closurecompiler-externs/process.js" + "js-yaml_externs.js"] + :warnings true + :elide-asserts true + :target :nodejs + :output-dir "app/dev/js/out_main" + :source-map true + :optimizations :none + :main "madek.app.main.main" + :pretty-print true + :output-wrapper true}} + :electron-main-prod + {:source-paths ["electron_main/src/all" "electron_main/src/prod"] + :incremental true + :jar true + :assert true + :compiler {:output-to "app/prod/js/main.js" + :externs ["app/prod/js/main_externs.js" + "node_modules/closurecompiler-externs/path.js" + "node_modules/closurecompiler-externs/process.js"] + :warnings true + :elide-asserts true + :target :nodejs + :output-dir "app/prod/js/out_main" + :optimizations :advanced + :source-map "app/prod/js/main.js.map" + :pretty-print true + :output-wrapper true}} + :electron-front-dev + {:source-paths ["electron_front/src/all" "electron_front/src/dev"] + :incremental true ;:figwheel {:on-jsload madek.main/init!} - :jar true - :assert true - :compiler {:output-to "app/dev/js/front.js" - :externs ["app/dev/js/front_externs.js"] - :warnings true - :elide-asserts true - :optimizations :none - :main "madek.app.front.init" - :output-dir "app/dev/js/out_front" - :asset-path "js/out_front" - :source-map true - :pretty-print true - :output-wrapper true}} - :electron-front-prod - {:source-paths ["electron_front/src/all" "electron_front/src/prod"] - :incremental true - :jar true - :assert true - :compiler {:output-to "app/prod/js/front.js" - :externs ["app/prod/js/front_externs.js"] - :warnings true - :elide-asserts true - :output-dir "app/prod/js/out_front" - :optimizations :advanced - :source-map "app/prod/js/front.js.map" - :pretty-print true - :output-wrapper true}} - :uberjar { - :source-paths ["jvm_main/src"] - :jar false - :compiler {} - } - }} -:figwheel {:http-server-root "public" - :ring-handler madek.app.front.figwheel-middleware/app - :server-port 8384}) + :jar true + :assert true + :compiler {:output-to "app/dev/js/front.js" + :externs ["app/dev/js/front_externs.js"] + :warnings true + :elide-asserts true + :optimizations :none + :main "madek.app.front.init" + :output-dir "app/dev/js/out_front" + :asset-path "js/out_front" + :source-map true + :pretty-print true + :output-wrapper true}} + :electron-front-prod + {:source-paths ["electron_front/src/all" "electron_front/src/prod"] + :incremental true + :jar true + :assert true + :compiler {:output-to "app/prod/js/front.js" + :externs ["app/prod/js/front_externs.js"] + :warnings true + :elide-asserts true + :output-dir "app/prod/js/out_front" + :optimizations :advanced + :source-map "app/prod/js/front.js.map" + :pretty-print true + :output-wrapper true}} + :uberjar {:source-paths ["jvm_main/src"] + :jar false + :compiler {}}}} + + :figwheel {:http-server-root "public" + :ring-handler madek.app.front.figwheel-middleware/app + :server-port 8384}) diff --git a/releases.yml b/releases.yml index 16195f9..a8b8004 100644 --- a/releases.yml +++ b/releases.yml @@ -1,3 +1,31 @@ + +####### 0.9.8 ####################################################################### + +- version_major: 0 + version_minor: 10 + version_patch: 0 + version_pre: 0 + version_build: NULL + name: NULL + + description: | + + Fixes and Features + ------------------ + + * Fix certificate issues. + * Fix html page with respect to roles. + * Resolve and display role data within roles. + * Resolve and display person data within roles. + + Notes + ----- + + * The exporter only supports Mac OS from this release on. + * The CSS (re-)build doesn't work. + + + ####### 0.9.7 ####################################################################### - version_major: 0 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e391d46..06656db 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,4 @@ require 'active_support/all' -require 'capybara/poltergeist' require 'capybara/rspec' require 'chromedriver/helper' require 'logger' @@ -15,7 +14,7 @@ APP_BINARY = \ case RUBY_PLATFORM - when 'x86_64-darwin16' + when 'x86_64-darwin16', 'arm64-darwin22' APP_ROOT_DIR.join( 'madek-exporter-darwin-x64/madek-exporter.app/Contents/MacOS/madek-exporter').to_s when 'x86_64-linux', 'x86_64-linux-gnu' @@ -74,12 +73,6 @@ def take_screenshot(screenshot_dir = nil, name = nil) rescue nil end - when :poltergeist - begin - page.driver.render(path, full: true) - rescue - nil - end else Rails.logger.warn 'Taking screenshots is not implemented for ' \ "#{Capybara.current_driver}." diff --git a/vendor b/vendor index 28c0485..2a30a09 160000 --- a/vendor +++ b/vendor @@ -1 +1 @@ -Subproject commit 28c0485289b25f36cc07c54b7b6d76cc21039f64 +Subproject commit 2a30a095058196438635b4959389368619106eb8