├── .gitattributes ├── .github └── workflows │ └── upload.yaml ├── .gitignore ├── README.md ├── calcit.cirru ├── cli └── build │ └── main.clj ├── entry ├── cumulo.png ├── main.css └── manifest.json ├── package.json ├── shadow-cljs.edn ├── src └── app │ ├── client.cljs │ ├── comp │ ├── container.cljs │ ├── login.cljs │ ├── navigation.cljs │ └── profile.cljs │ ├── config.cljs │ ├── page.cljs │ ├── schema.cljs │ ├── server.cljs │ ├── twig │ ├── container.cljs │ └── user.cljs │ ├── updater.cljs │ └── updater │ ├── router.cljs │ ├── session.cljs │ └── user.cljs ├── upload.cirru └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | 2 | calcit.edn -diff linguist-generated 3 | calcit.cirru -diff 4 | yarn.lock -diff linguist-generated 5 | -------------------------------------------------------------------------------- /.github/workflows/upload.yaml: -------------------------------------------------------------------------------- 1 | 2 | name: Upload Assets 3 | 4 | on: 5 | pull_request: {} 6 | push: 7 | branches: 8 | - master 9 | 10 | jobs: 11 | upload-assets: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: docker://timbru31/java-node:latest 16 | 17 | - name: Get yarn cache 18 | id: yarn-cache 19 | run: echo "::set-output name=dir::$(yarn cache dir)" 20 | 21 | - uses: actions/cache@v1 22 | name: Cache node modules of yarn 23 | with: 24 | path: ${{ steps.yarn-cache.outputs.dir }} 25 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 26 | restore-keys: | 27 | ${{ runner.os }}-yarn- 28 | 29 | - name: Cache Clojars 30 | uses: actions/cache@v1 31 | env: 32 | cache-name: cache-clojars 33 | with: 34 | path: ~/.m2/repository 35 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('shadow-cljs.edn') }} 36 | restore-keys: | 37 | ${{ runner.os }}-clojars 38 | 39 | - run: yarn && yarn build 40 | name: Build web assets 41 | 42 | - run: mkdir -p dist-server && mv dist/server.js dist-server && cp package.json dist-server/ 43 | name: Copy server scripts 44 | 45 | - name: Upload web assets 46 | id: deploy 47 | uses: Pendect/action-rsyncer@v1.1.0 48 | env: 49 | DEPLOY_KEY: ${{secrets.rsync_private_key}} 50 | with: 51 | flags: '-avzr --progress' 52 | options: '' 53 | ssh_options: '' 54 | src: 'dist/*' 55 | dest: 'rsync-user@tiye.me:/web-assets/repo/${{ github.repository }}' 56 | 57 | - name: Display status from deploy 58 | run: echo "${{ steps.deploy.outputs.status }}" 59 | 60 | - name: Upload server script 61 | id: deploy-server 62 | uses: Pendect/action-rsyncer@v1.1.0 63 | env: 64 | DEPLOY_KEY: ${{secrets.rsync_private_key}} 65 | with: 66 | flags: '-avzr --progress' 67 | options: '' 68 | ssh_options: '' 69 | src: 'dist-server/*' 70 | dest: 'rsync-user@tiye.me:/servers/workflow' 71 | 72 | - name: Display status from deploy 73 | run: echo "${{ steps.deploy-server.outputs.status }}" 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | /dist 4 | /node_modules 5 | .shadow-cljs/ 6 | .cpcache/ 7 | .nrepl-port 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Cumulo Workflow 3 | ------ 4 | 5 | > Personal project template for creating realtime apps. Accomplished with [recollect](https://github.com/Cumulo/recollect) and [calcit-workrlow](https://github.com/mvc-works/calcit-workflow). 6 | 7 | Features: 8 | 9 | * hot swapping client & server 10 | * developing realtime app like building an SPA 11 | * all in ClojureScript 12 | 13 | View showcases on http://topix.im/ . 14 | 15 | ### Usages 16 | 17 | To develop: 18 | 19 | ```bash 20 | yarn 21 | yarn watch # dev building client and server code 22 | 23 | # another terminal 24 | node target/server.js 25 | 26 | yarn page # generates target/index.html 27 | # open http://localhost:7000 28 | ``` 29 | 30 | To build and optimize: 31 | 32 | ```bash 33 | yarn build 34 | ``` 35 | 36 | Code is editing with [calcit-editor](https://github.com/Cirru/calcit-editor). 37 | 38 | ### Workflow 39 | 40 | https://github.com/Cumulo/cumulo-workflow 41 | 42 | ### License 43 | 44 | MIT 45 | -------------------------------------------------------------------------------- /cli/build/main.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns build.main 3 | (:require [shadow.cljs.devtools.api :as shadow] 4 | [clojure.java.shell :refer [sh]])) 5 | 6 | (defn sh! [command] 7 | (println command) 8 | (println (:out (sh "bash" "-c" command)))) 9 | 10 | (defn build-cdn [] 11 | (sh! "rm -rf dist/*") 12 | (shadow/release :client) 13 | (shadow/release :server) 14 | (shadow/compile :page) 15 | (sh! "release=true cdn=true node target/page.js") 16 | (sh! "cp package.json dist/") 17 | (sh! "cp entry/manifest.json dist/")) 18 | 19 | (defn build [] 20 | (sh! "rm -rf dist/*") 21 | (shadow/release :client) 22 | (shadow/release :server) 23 | (shadow/compile :page) 24 | (sh! "release=true node target/page.js") 25 | (sh! "cp package.json dist/") 26 | (sh! "cp entry/manifest.json dist/")) 27 | 28 | (defn page [] 29 | (shadow/compile :page) 30 | (sh! "node target/page.js") 31 | (sh! "cp entry/manifest.json target/")) 32 | -------------------------------------------------------------------------------- /entry/cumulo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cumulo/cumulo-workflow/5ce0c67783fa8fa18c4dff02a4924ce31ed1b249/entry/cumulo.png -------------------------------------------------------------------------------- /entry/main.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | margin: 0; 4 | overscroll-behavior-y: none; 5 | } 6 | 7 | body * { 8 | box-sizing: border-box; 9 | flex-shrink: 0; 10 | } 11 | 12 | .dev-shadows, 13 | .dev-shadows * { 14 | box-shadow: 0 0 1px hsla(0,0%,0%,0.3); 15 | } 16 | -------------------------------------------------------------------------------- /entry/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Cumulo", 3 | "name": "Cumulo", 4 | "icons": [ 5 | { 6 | "src": "http://cdn.tiye.me/logo/cumulo.png", 7 | "sizes": "460x460" 8 | } 9 | ], 10 | "start_url": "index.html", 11 | "display": "standalone", 12 | "orientation": "portrait", 13 | "background_color": "#eeeeff", 14 | "theme_color": "#eeeeff" 15 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cumulo-workflow", 3 | "version": "0.1.0", 4 | "description": "Cumulo Workflow", 5 | "main": "index.js", 6 | "scripts": { 7 | "watch": "shadow-cljs watch client server", 8 | "build-cdn": "shadow-cljs clj-run build.main/build-cdn", 9 | "build": "shadow-cljs clj-run build.main/build", 10 | "page": "shadow-cljs clj-run build.main/page", 11 | "up": "yarn build-cdn && tiye-up", 12 | "ln": "cd target && rm -f entry && ln -s ../entry", 13 | "prod": "yarn install --production" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git@github.com:mvc-works/cumulo-workflow.git" 18 | }, 19 | "author": "jiyinyiyong", 20 | "license": "MIT", 21 | "dependencies": { 22 | "md5": "^2.3.0", 23 | "randomcolor": "^0.6.2", 24 | "shortid": "^2.2.16", 25 | "ws": "^7.5.10" 26 | }, 27 | "devDependencies": { 28 | "feather-icons": "^4.28.0", 29 | "node-notifier": "^9.0.0", 30 | "shadow-cljs": "^2.11.18", 31 | "source-map-support": "^0.5.19", 32 | "url-parse": "^1.5.9" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /shadow-cljs.edn: -------------------------------------------------------------------------------- 1 | { 2 | :source-paths ["src" "cli"] 3 | :cache-blockers #{cumulo-util.build} 4 | :dependencies [ 5 | [mvc-works/hsl "0.1.2"] 6 | [mvc-works/shell-page "0.1.15"] 7 | [mvc-works/ws-edn "0.1.4"] 8 | [cumulo/recollect "0.6.4"] 9 | [cumulo/reel "0.2.0"] 10 | [cumulo/util "0.1.12"] 11 | [cumulo/memof "0.2.3"] 12 | [respo "0.13.9"] 13 | [respo/ui "0.3.16"] 14 | [respo/alerts "0.5.5"] 15 | [respo/message "0.3.6"] 16 | [respo/feather "0.1.1"] 17 | [cirru/bisection-key "0.1.6"] 18 | [cirru/favored-edn "0.1.4"] 19 | [medley "1.3.0"] 20 | [applied-science/js-interop "0.2.7"] 21 | [org.clojure/core.incubator "0.1.4"] 22 | ] 23 | :open-file-command [ 24 | "subl" 25 | ["%s:%s:%s" :file :line :column] 26 | ] 27 | :dev-http {7000 "target"} 28 | :builds { 29 | :client { 30 | :output-dir "target/", :asset-path "./", :target :browser, :module-hash-names 8 31 | :modules { 32 | :client {:init-fn app.client/main!} 33 | } 34 | :release {:output-dir "dist/"} 35 | :build-options {:manifest-name "assets.edn"} 36 | } 37 | :server { 38 | :target :node-script, :output-to "target/server.js", :main app.server/main! 39 | :devtools { 40 | :build-notify cumulo-util.build-info/on-build! 41 | :preloads [cumulo-util.build-info] 42 | } 43 | :release {:output-to "dist/server.js"} 44 | } 45 | :page { 46 | :target :node-script, :output-to "target/page.js", :main app.page/main! 47 | :devtools {:after-load app.page/main!} 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/app/client.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.client 3 | (:require [respo.core :refer [render! clear-cache! realize-ssr!]] 4 | [respo.cursor :refer [update-states]] 5 | [app.comp.container :refer [comp-container]] 6 | [cljs.reader :refer [read-string]] 7 | [app.schema :as schema] 8 | [app.config :as config] 9 | [ws-edn.client :refer [ws-connect! ws-send!]] 10 | [recollect.patch :refer [patch-twig]] 11 | [cumulo-util.core :refer [on-page-touch]] 12 | ["url-parse" :as url-parse] 13 | [applied-science.js-interop :as j]) 14 | (:require-macros [clojure.core.strint :refer [<<]])) 15 | 16 | (declare dispatch!) 17 | 18 | (declare connect!) 19 | 20 | (declare simulate-login!) 21 | 22 | (defonce *states (atom {:states {:cursor []}})) 23 | 24 | (defonce *store (atom nil)) 25 | 26 | (defn simulate-login! [] 27 | (let [raw (.getItem js/localStorage (:storage-key config/site))] 28 | (if (some? raw) 29 | (do (println "Found storage.") (dispatch! :user/log-in (read-string raw))) 30 | (do (println "Found no storage."))))) 31 | 32 | (defn dispatch! [op op-data] 33 | (when (and config/dev? (not= op :states)) (println "Dispatch" op op-data)) 34 | (case op 35 | :states (reset! *states (update-states @*states op-data)) 36 | :effect/connect (connect!) 37 | (ws-send! {:kind :op, :op op, :data op-data}))) 38 | 39 | (defn connect! [] 40 | (let [url-obj (url-parse js/location.href true) 41 | host (or (j/get-in url-obj [:query :host]) js/location.hostname) 42 | port (or (j/get-in url-obj [:query :port]) (:port config/site))] 43 | (ws-connect! 44 | (<< "ws://~{host}:~{port}") 45 | {:on-open (fn [] (simulate-login!)), 46 | :on-close (fn [event] (reset! *store nil) (js/console.error "Lost connection!")), 47 | :on-data (fn [data] 48 | (case (:kind data) 49 | :patch 50 | (let [changes (:data data)] 51 | (when config/dev? (js/console.log "Changes" (clj->js changes))) 52 | (reset! *store (patch-twig @*store changes))) 53 | (println "unknown kind:" data)))}))) 54 | 55 | (def mount-target (.querySelector js/document ".app")) 56 | 57 | (defn render-app! [renderer] 58 | (renderer mount-target (comp-container (:states @*states) @*store) dispatch!)) 59 | 60 | (def ssr? (some? (.querySelector js/document "meta.respo-ssr"))) 61 | 62 | (defn main! [] 63 | (println "Running mode:" (if config/dev? "dev" "release")) 64 | (if ssr? (render-app! realize-ssr!)) 65 | (render-app! render!) 66 | (connect!) 67 | (add-watch *store :changes #(render-app! render!)) 68 | (add-watch *states :changes #(render-app! render!)) 69 | (on-page-touch #(if (nil? @*store) (connect!))) 70 | (println "App started!")) 71 | 72 | (defn ^:dev/after-load 73 | reload! 74 | [] 75 | (clear-cache!) 76 | (render-app! render!) 77 | (println "Code updated.")) 78 | -------------------------------------------------------------------------------- /src/app/comp/container.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.comp.container 3 | (:require [hsl.core :refer [hsl]] 4 | [respo-ui.core :as ui] 5 | [respo.core :refer [defcomp <> >> div span button]] 6 | [respo.comp.inspect :refer [comp-inspect]] 7 | [respo.comp.space :refer [=<]] 8 | [app.comp.navigation :refer [comp-navigation]] 9 | [app.comp.profile :refer [comp-profile]] 10 | [app.comp.login :refer [comp-login]] 11 | [respo-message.comp.messages :refer [comp-messages]] 12 | [cumulo-reel.comp.reel :refer [comp-reel]] 13 | [app.config :refer [dev?]] 14 | [app.schema :as schema] 15 | [app.config :as config])) 16 | 17 | (defcomp 18 | comp-offline 19 | () 20 | (div 21 | {:style (merge 22 | ui/global 23 | ui/fullscreen 24 | ui/column-dispersive 25 | {:background-color (:theme config/site)})} 26 | (div {:style {:height 0}}) 27 | (div 28 | {:style {:background-image (str "url(" (:icon config/site) ")"), 29 | :width 128, 30 | :height 128, 31 | :background-size :contain}}) 32 | (div 33 | {:style {:cursor :pointer, :line-height "32px"}, 34 | :on-click (fn [e d!] (d! :effect/connect nil))} 35 | (<> "No connection..." {:font-family ui/font-fancy, :font-size 24})))) 36 | 37 | (defcomp 38 | comp-status-color 39 | (color) 40 | (div 41 | {:style (let [size 24] 42 | {:width size, 43 | :height size, 44 | :position :absolute, 45 | :bottom 60, 46 | :left 8, 47 | :background-color color, 48 | :border-radius "50%", 49 | :opacity 0.6, 50 | :pointer-events :none})})) 51 | 52 | (defcomp 53 | comp-container 54 | (states store) 55 | (let [state (:data states) 56 | session (:session store) 57 | router (:router store) 58 | router-data (:data router)] 59 | (if (nil? store) 60 | (comp-offline) 61 | (div 62 | {:style (merge ui/global ui/fullscreen ui/column)} 63 | (comp-navigation (:logged-in? store) (:count store)) 64 | (if (:logged-in? store) 65 | (case (:name router) 66 | :home (<> "Home") 67 | :profile (comp-profile (:user store) (:data router)) 68 | (<> router)) 69 | (comp-login (>> states :login))) 70 | (comp-status-color (:color store)) 71 | (when dev? (comp-inspect "Store" store {:bottom 0, :left 0, :max-width "100%"})) 72 | (comp-messages 73 | (get-in store [:session :messages]) 74 | {} 75 | (fn [info d!] (d! :session/remove-message info))) 76 | (when dev? (comp-reel (:reel-length store) {})))))) 77 | -------------------------------------------------------------------------------- /src/app/comp/login.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.comp.login 3 | (:require [respo.core :refer [defcomp <> div input button span]] 4 | [respo.comp.space :refer [=<]] 5 | [respo.comp.inspect :refer [comp-inspect]] 6 | [respo-ui.core :as ui] 7 | [app.schema :as schema] 8 | [app.config :as config])) 9 | 10 | (def initial-state {:username "", :password ""}) 11 | 12 | (defn on-submit [username password signup?] 13 | (fn [e dispatch!] 14 | (dispatch! (if signup? :user/sign-up :user/log-in) [username password]) 15 | (.setItem js/localStorage (:storage-key config/site) [username password]))) 16 | 17 | (defcomp 18 | comp-login 19 | (states) 20 | (let [cursor (:cursor states), state (or (:data states) initial-state)] 21 | (div 22 | {:style (merge ui/flex ui/center)} 23 | (div 24 | {} 25 | (div 26 | {:style {}} 27 | (div 28 | {} 29 | (input 30 | {:placeholder "Username", 31 | :value (:username state), 32 | :style ui/input, 33 | :on-input (fn [e d!] (d! cursor (assoc state :username (:value e))))})) 34 | (=< nil 8) 35 | (div 36 | {} 37 | (input 38 | {:placeholder "Password", 39 | :value (:password state), 40 | :style ui/input, 41 | :on-input (fn [e d!] (d! cursor (assoc state :password (:value e))))}))) 42 | (=< nil 8) 43 | (div 44 | {:style {:text-align :right}} 45 | (span 46 | {:inner-text "Sign up", 47 | :style (merge ui/link), 48 | :on-click (on-submit (:username state) (:password state) true)}) 49 | (=< 8 nil) 50 | (span 51 | {:inner-text "Log in", 52 | :style (merge ui/link), 53 | :on-click (on-submit (:username state) (:password state) false)})))))) 54 | -------------------------------------------------------------------------------- /src/app/comp/navigation.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.comp.navigation 3 | (:require [hsl.core :refer [hsl]] 4 | [respo-ui.core :as ui] 5 | [respo.comp.space :refer [=<]] 6 | [respo.core :refer [defcomp <> span div]] 7 | [app.config :as config])) 8 | 9 | (defcomp 10 | comp-navigation 11 | (logged-in? count-members) 12 | (div 13 | {:style (merge 14 | ui/row-center 15 | {:height 48, 16 | :justify-content :space-between, 17 | :padding "0 16px", 18 | :font-size 16, 19 | :border-bottom (str "1px solid " (hsl 0 0 0 0.1)), 20 | :font-family ui/font-fancy})} 21 | (div 22 | {:on-click (fn [e d!] (d! :router/change {:name :home})), :style {:cursor :pointer}} 23 | (<> (:title config/site) nil)) 24 | (div 25 | {:style {:cursor "pointer"}, :on-click (fn [e d!] (d! :router/change {:name :profile}))} 26 | (<> (if logged-in? "Me" "Guest")) 27 | (=< 8 nil) 28 | (<> count-members)))) 29 | -------------------------------------------------------------------------------- /src/app/comp/profile.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.comp.profile 3 | (:require [hsl.core :refer [hsl]] 4 | [app.schema :as schema] 5 | [respo-ui.core :as ui] 6 | [respo.core :refer [defcomp list-> <> span div button]] 7 | [respo.comp.space :refer [=<]] 8 | [app.config :as config])) 9 | 10 | (defcomp 11 | comp-profile 12 | (user members) 13 | (div 14 | {:style (merge ui/flex {:padding 16})} 15 | (div 16 | {:style {:font-family ui/font-fancy, :font-size 32, :font-weight 100}} 17 | (<> (str "Hello! " (:name user)))) 18 | (=< nil 16) 19 | (div 20 | {:style ui/row} 21 | (<> "Members:") 22 | (=< 8 nil) 23 | (list-> 24 | {:style ui/row} 25 | (->> members 26 | (map 27 | (fn [[k username]] 28 | [k 29 | (div 30 | {:style {:padding "0 8px", 31 | :border (str "1px solid " (hsl 0 0 80)), 32 | :border-radius "16px", 33 | :margin "0 4px"}} 34 | (<> username))]))))) 35 | (=< nil 48) 36 | (div 37 | {} 38 | (button 39 | {:style (merge ui/button), 40 | :on-click (fn [e d!] 41 | (js/location.replace (str js/location.origin "?time=" (.now js/Date))))} 42 | (<> "Refresh")) 43 | (=< 8 nil) 44 | (button 45 | {:style (merge ui/button {:color :red, :border-color :red}), 46 | :on-click (fn [e dispatch!] 47 | (dispatch! :user/log-out nil) 48 | (.removeItem js/localStorage (:storage-key config/site)))} 49 | (<> "Log out"))))) 50 | -------------------------------------------------------------------------------- /src/app/config.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.config ) 3 | 4 | (def cdn? 5 | (cond 6 | (exists? js/window) false 7 | (exists? js/process) (= "true" js/process.env.cdn) 8 | :else false)) 9 | 10 | (def dev? 11 | (let [debug? (do ^boolean js/goog.DEBUG)] 12 | (if debug? 13 | (cond 14 | (exists? js/window) true 15 | (exists? js/process) (not= "true" js/process.env.release) 16 | :else true) 17 | false))) 18 | 19 | (def site 20 | {:port 5021, 21 | :title "Cumulo", 22 | :icon "http://cdn.tiye.me/logo/cumulo.png", 23 | :dev-ui "http://localhost:8100/main.css", 24 | :release-ui "http://cdn.tiye.me/favored-fonts/main.css", 25 | :cdn-url "http://cdn.tiye.me/cumulo-workflow/", 26 | :theme "#eeeeff", 27 | :storage-key "workflow-storage", 28 | :storage-file "storage.edn"}) 29 | -------------------------------------------------------------------------------- /src/app/page.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.page 3 | (:require [respo.render.html :refer [make-string]] 4 | [shell-page.core :refer [make-page spit slurp]] 5 | [app.comp.container :refer [comp-container]] 6 | [cljs.reader :refer [read-string]] 7 | [app.schema :as schema] 8 | [app.config :as config] 9 | [cumulo-util.build :refer [get-ip!]]) 10 | (:require-macros [clojure.core.strint :refer [<<]])) 11 | 12 | (def base-info 13 | {:title (:title config/site), 14 | :icon (:icon config/site), 15 | :ssr nil, 16 | :inline-styles [(slurp "entry/main.css")]}) 17 | 18 | (defn dev-page [] 19 | (make-page 20 | "" 21 | (merge 22 | base-info 23 | {:styles [(<< "http://~(get-ip!):8100/main.css") "/entry/main.css"], 24 | :scripts [{:src "/client.js", :defer? true}], 25 | :inline-styles []}))) 26 | 27 | (defn prod-page [] 28 | (let [html-content (make-string (comp-container {} nil)) 29 | assets (read-string (slurp "dist/assets.edn")) 30 | cdn (if config/cdn? (:cdn-url config/site) "") 31 | prefix-cdn #(str cdn %)] 32 | (make-page 33 | html-content 34 | (merge 35 | base-info 36 | {:styles [(:release-ui config/site)], 37 | :scripts (map (fn [x] {:src (-> x :output-name prefix-cdn), :defer? true}) assets)})))) 38 | 39 | (defn main! [] 40 | (println "Running mode:" (if config/dev? "dev" "release")) 41 | (if config/dev? 42 | (spit "target/index.html" (dev-page)) 43 | (spit "dist/index.html" (prod-page)))) 44 | -------------------------------------------------------------------------------- /src/app/schema.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.schema ) 3 | 4 | (def router {:name nil, :title nil, :data {}, :router nil}) 5 | 6 | (def session 7 | {:user-id nil, 8 | :id nil, 9 | :nickname nil, 10 | :router (do router {:name :home, :data nil, :router nil}), 11 | :messages {}}) 12 | 13 | (def user {:name nil, :id nil, :nickname nil, :avatar nil, :password nil}) 14 | 15 | (def database {:sessions (do session {}), :users (do user {})}) 16 | -------------------------------------------------------------------------------- /src/app/server.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.server 3 | (:require [app.schema :as schema] 4 | [app.updater :refer [updater]] 5 | [cljs.reader :refer [read-string]] 6 | [cumulo-reel.core :refer [reel-reducer refresh-reel reel-schema]] 7 | ["fs" :as fs] 8 | ["path" :as path] 9 | [app.config :as config] 10 | [cumulo-util.file :refer [write-mildly! get-backup-path! merge-local-edn!]] 11 | [cumulo-util.core :refer [id! repeat! unix-time! delay!]] 12 | [app.twig.container :refer [twig-container]] 13 | [recollect.diff :refer [diff-twig]] 14 | [ws-edn.server :refer [wss-serve! wss-send! wss-each!]] 15 | [favored-edn.core :refer [write-edn]] 16 | [recollect.twig :refer [new-twig-loop! clear-twig-caches!]]) 17 | (:require-macros [clojure.core.strint :refer [<<]])) 18 | 19 | (defonce *client-caches (atom {})) 20 | 21 | (def storage-file (path/join js/__dirname (:storage-file config/site))) 22 | 23 | (defonce initial-db 24 | (merge-local-edn! 25 | schema/database 26 | storage-file 27 | (fn [found?] (if found? (println "Found local EDN data") (println "Found no data"))))) 28 | 29 | (defonce *reel (atom (merge reel-schema {:base initial-db, :db initial-db}))) 30 | 31 | (defonce *reader-reel (atom @*reel)) 32 | 33 | (defn persist-db! [] 34 | (let [file-content (write-edn (assoc (:db @*reel) :sessions {})) 35 | storage-path storage-file 36 | backup-path (get-backup-path!)] 37 | (write-mildly! storage-path file-content) 38 | (write-mildly! backup-path file-content))) 39 | 40 | (defn dispatch! [op op-data sid] 41 | (let [op-id (id!), op-time (unix-time!)] 42 | (if config/dev? (println "Dispatch!" (str op) op-data sid)) 43 | (try 44 | (cond 45 | (= op :effect/persist) (persist-db!) 46 | :else (reset! *reel (reel-reducer @*reel updater op op-data sid op-id op-time))) 47 | (catch js/Error error (js/console.error error))))) 48 | 49 | (defn on-exit! [code] 50 | (persist-db!) 51 | (comment println "exit code is:" (pr-str code)) 52 | (js/process.exit)) 53 | 54 | (defn sync-clients! [reel] 55 | (wss-each! 56 | (fn [sid socket] 57 | (let [db (:db reel) 58 | records (:records reel) 59 | session (get-in db [:sessions sid]) 60 | old-store (or (get @*client-caches sid) nil) 61 | new-store (twig-container db session records) 62 | changes (diff-twig old-store new-store {:key :id})] 63 | (when config/dev? (println "Changes for" sid ":" changes (count records))) 64 | (if (not= changes []) 65 | (do 66 | (wss-send! sid {:kind :patch, :data changes}) 67 | (swap! *client-caches assoc sid new-store)))))) 68 | (new-twig-loop!)) 69 | 70 | (defn render-loop! [] 71 | (when (not (identical? @*reader-reel @*reel)) 72 | (reset! *reader-reel @*reel) 73 | (sync-clients! @*reader-reel)) 74 | (delay! 0.2 render-loop!)) 75 | 76 | (defn run-server! [port] 77 | (wss-serve! 78 | port 79 | {:on-open (fn [sid socket] 80 | (dispatch! :session/connect nil sid) 81 | (js/console.info "New client.")), 82 | :on-data (fn [sid action] 83 | (case (:kind action) 84 | :op (dispatch! (:op action) (:data action) sid) 85 | (println "unknown data" action))), 86 | :on-close (fn [sid event] 87 | (js/console.warn "Client closed!") 88 | (dispatch! :session/disconnect nil sid)), 89 | :on-error (fn [error] (.error js/console error))})) 90 | 91 | (defn main! [] 92 | (println "Running mode:" (if config/dev? "dev" "release")) 93 | (let [port (if (some? js/process.env.port) 94 | (js/parseInt js/process.env.port) 95 | (:port config/site))] 96 | (run-server! port) 97 | (println (<< "Server started on port ~{port}."))) 98 | (render-loop!) 99 | (js/process.on "SIGINT" on-exit!) 100 | (repeat! 600 #(persist-db!))) 101 | 102 | (defn ^:dev/after-load 103 | reload! 104 | [] 105 | (println "Code updated.") 106 | (clear-twig-caches!) 107 | (reset! *reel (refresh-reel @*reel initial-db updater)) 108 | (sync-clients! @*reader-reel)) 109 | -------------------------------------------------------------------------------- /src/app/twig/container.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.twig.container 3 | (:require [app.twig.user :refer [twig-user]] 4 | ["randomcolor" :as color] 5 | [memof.alias :refer [memof-call]])) 6 | 7 | (defn twig-members [sessions users] 8 | (->> sessions 9 | (map (fn [[k session]] [k (get-in users [(:user-id session) :name])])) 10 | (into {}))) 11 | 12 | (defn twig-container [db session records] 13 | (let [logged-in? (some? (:user-id session)) 14 | router (:router session) 15 | base-data {:logged-in? logged-in?, :session session, :reel-length (count records)}] 16 | (merge 17 | base-data 18 | (if logged-in? 19 | {:user (memof-call twig-user (get-in db [:users (:user-id session)])), 20 | :router (assoc 21 | router 22 | :data 23 | (case (:name router) 24 | :home (:pages db) 25 | :profile (memof-call twig-members (:sessions db) (:users db)) 26 | {})), 27 | :count (count (:sessions db)), 28 | :color (color/randomColor)} 29 | nil)))) 30 | -------------------------------------------------------------------------------- /src/app/twig/user.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.twig.user (:require )) 3 | 4 | (defn twig-user [user] (dissoc user :password)) 5 | -------------------------------------------------------------------------------- /src/app/updater.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.updater 3 | (:require [app.updater.session :as session] 4 | [app.updater.user :as user] 5 | [app.updater.router :as router] 6 | [app.schema :as schema] 7 | [respo-message.updater :refer [update-messages]])) 8 | 9 | (defn updater [db op op-data sid op-id op-time] 10 | (let [session (get-in db [:sessions sid]) 11 | user (get-in db [:users (:user-id session)]) 12 | f (case op 13 | :session/connect session/connect 14 | :session/disconnect session/disconnect 15 | :session/remove-message session/remove-message 16 | :user/log-in user/log-in 17 | :user/sign-up user/sign-up 18 | :user/log-out user/log-out 19 | :router/change router/change 20 | (do (println "Unknown op:" op) identity))] 21 | (f db op-data sid op-id op-time session user))) 22 | -------------------------------------------------------------------------------- /src/app/updater/router.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.updater.router ) 3 | 4 | (defn change [db op-data sid op-id op-time] (assoc-in db [:sessions sid :router] op-data)) 5 | -------------------------------------------------------------------------------- /src/app/updater/session.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.updater.session (:require [app.schema :as schema])) 3 | 4 | (defn connect [db op-data sid op-id op-time] 5 | (assoc-in db [:sessions sid] (merge schema/session {:id sid}))) 6 | 7 | (defn disconnect [db op-data sid op-id op-time] 8 | (update db :sessions (fn [session] (dissoc session sid)))) 9 | 10 | (defn remove-message [db op-data sid op-id op-time] 11 | (update-in db [:sessions sid :messages] (fn [messages] (dissoc messages (:id op-data))))) 12 | -------------------------------------------------------------------------------- /src/app/updater/user.cljs: -------------------------------------------------------------------------------- 1 | 2 | (ns app.updater.user (:require [cumulo-util.core :refer [find-first]] ["md5" :as md5])) 3 | 4 | (defn log-in [db op-data sid op-id op-time] 5 | (let [[username password] op-data 6 | maybe-user (find-first 7 | (fn [user] (and (= username (:name user)))) 8 | (vals (:users db)))] 9 | (update-in 10 | db 11 | [:sessions sid] 12 | (fn [session] 13 | (if (some? maybe-user) 14 | (if (= (md5 password) (:password maybe-user)) 15 | (assoc session :user-id (:id maybe-user)) 16 | (update 17 | session 18 | :messages 19 | (fn [messages] 20 | (assoc messages op-id {:id op-id, :text (str "Wrong password for " username)})))) 21 | (update 22 | session 23 | :messages 24 | (fn [messages] 25 | (assoc messages op-id {:id op-id, :text (str "No user named: " username)})))))))) 26 | 27 | (defn log-out [db op-data sid op-id op-time] (assoc-in db [:sessions sid :user-id] nil)) 28 | 29 | (defn sign-up [db op-data sid op-id op-time] 30 | (let [[username password] op-data 31 | maybe-user (find-first (fn [user] (= username (:name user))) (vals (:users db)))] 32 | (if (some? maybe-user) 33 | (update-in 34 | db 35 | [:sessions sid :messages] 36 | (fn [messages] 37 | (assoc messages op-id {:id op-id, :text (str "Name is taken: " username)}))) 38 | (-> db 39 | (assoc-in [:sessions sid :user-id] op-id) 40 | (assoc-in 41 | [:users op-id] 42 | {:id op-id, 43 | :name username, 44 | :nickname username, 45 | :password (md5 password), 46 | :avatar nil}))))) 47 | -------------------------------------------------------------------------------- /upload.cirru: -------------------------------------------------------------------------------- 1 | 2 | {} (:host |cumulo.org) 3 | :uploads $ [] 4 | {} (:from |dist/*) (:to |/web-assets/cdn/cumulo-workflow/) 5 | {} (:from |dist/{index.html,manifest.json}) (:to |/web-assets/repo/Cumulo/workflow/) 6 | {} (:from |dist/{server.js,package.json}) (:to |/servers/workflow/) 7 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | asn1.js@^5.2.0: 6 | version "5.4.1" 7 | resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" 8 | integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== 9 | dependencies: 10 | bn.js "^4.0.0" 11 | inherits "^2.0.1" 12 | minimalistic-assert "^1.0.0" 13 | safer-buffer "^2.1.0" 14 | 15 | assert@^1.1.1: 16 | version "1.5.0" 17 | resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" 18 | integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== 19 | dependencies: 20 | object-assign "^4.1.1" 21 | util "0.10.3" 22 | 23 | async-limiter@~1.0.0: 24 | version "1.0.1" 25 | resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" 26 | integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== 27 | 28 | base64-js@^1.0.2: 29 | version "1.5.1" 30 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 31 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 32 | 33 | bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: 34 | version "4.12.0" 35 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" 36 | integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== 37 | 38 | bn.js@^5.0.0: 39 | version "5.2.0" 40 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" 41 | integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== 42 | 43 | bn.js@^5.2.1: 44 | version "5.2.1" 45 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" 46 | integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== 47 | 48 | brorand@^1.0.1, brorand@^1.1.0: 49 | version "1.1.0" 50 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" 51 | integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= 52 | 53 | browserify-aes@^1.0.0, browserify-aes@^1.0.4: 54 | version "1.2.0" 55 | resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" 56 | integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== 57 | dependencies: 58 | buffer-xor "^1.0.3" 59 | cipher-base "^1.0.0" 60 | create-hash "^1.1.0" 61 | evp_bytestokey "^1.0.3" 62 | inherits "^2.0.1" 63 | safe-buffer "^5.0.1" 64 | 65 | browserify-cipher@^1.0.0: 66 | version "1.0.1" 67 | resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" 68 | integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== 69 | dependencies: 70 | browserify-aes "^1.0.4" 71 | browserify-des "^1.0.0" 72 | evp_bytestokey "^1.0.0" 73 | 74 | browserify-des@^1.0.0: 75 | version "1.0.2" 76 | resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" 77 | integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== 78 | dependencies: 79 | cipher-base "^1.0.1" 80 | des.js "^1.0.0" 81 | inherits "^2.0.1" 82 | safe-buffer "^5.1.2" 83 | 84 | browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: 85 | version "4.1.0" 86 | resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" 87 | integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== 88 | dependencies: 89 | bn.js "^5.0.0" 90 | randombytes "^2.0.1" 91 | 92 | browserify-sign@^4.0.0: 93 | version "4.2.2" 94 | resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" 95 | integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== 96 | dependencies: 97 | bn.js "^5.2.1" 98 | browserify-rsa "^4.1.0" 99 | create-hash "^1.2.0" 100 | create-hmac "^1.1.7" 101 | elliptic "^6.5.4" 102 | inherits "^2.0.4" 103 | parse-asn1 "^5.1.6" 104 | readable-stream "^3.6.2" 105 | safe-buffer "^5.2.1" 106 | 107 | browserify-zlib@^0.2.0: 108 | version "0.2.0" 109 | resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" 110 | integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== 111 | dependencies: 112 | pako "~1.0.5" 113 | 114 | buffer-from@^1.0.0: 115 | version "1.1.1" 116 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 117 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 118 | 119 | buffer-xor@^1.0.3: 120 | version "1.0.3" 121 | resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" 122 | integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= 123 | 124 | buffer@^4.3.0: 125 | version "4.9.2" 126 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" 127 | integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== 128 | dependencies: 129 | base64-js "^1.0.2" 130 | ieee754 "^1.1.4" 131 | isarray "^1.0.0" 132 | 133 | builtin-status-codes@^3.0.0: 134 | version "3.0.0" 135 | resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" 136 | integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= 137 | 138 | charenc@0.0.2: 139 | version "0.0.2" 140 | resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" 141 | integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= 142 | 143 | cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: 144 | version "1.0.4" 145 | resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" 146 | integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== 147 | dependencies: 148 | inherits "^2.0.1" 149 | safe-buffer "^5.0.1" 150 | 151 | classnames@^2.2.5: 152 | version "2.2.6" 153 | resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" 154 | integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== 155 | 156 | console-browserify@^1.1.0: 157 | version "1.2.0" 158 | resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" 159 | integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== 160 | 161 | constants-browserify@^1.0.0: 162 | version "1.0.0" 163 | resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" 164 | integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= 165 | 166 | core-js@^3.1.3: 167 | version "3.9.0" 168 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.0.tgz#790b1bb11553a2272b36e2625c7179db345492f8" 169 | integrity sha512-PyFBJaLq93FlyYdsndE5VaueA9K5cNB7CGzeCj191YYLhkQM0gdZR2SKihM70oF0wdqKSKClv/tEBOpoRmdOVQ== 170 | 171 | core-util-is@~1.0.0: 172 | version "1.0.2" 173 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 174 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 175 | 176 | create-ecdh@^4.0.0: 177 | version "4.0.4" 178 | resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" 179 | integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== 180 | dependencies: 181 | bn.js "^4.1.0" 182 | elliptic "^6.5.3" 183 | 184 | create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: 185 | version "1.2.0" 186 | resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" 187 | integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== 188 | dependencies: 189 | cipher-base "^1.0.1" 190 | inherits "^2.0.1" 191 | md5.js "^1.3.4" 192 | ripemd160 "^2.0.1" 193 | sha.js "^2.4.0" 194 | 195 | create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: 196 | version "1.1.7" 197 | resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" 198 | integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== 199 | dependencies: 200 | cipher-base "^1.0.3" 201 | create-hash "^1.1.0" 202 | inherits "^2.0.1" 203 | ripemd160 "^2.0.0" 204 | safe-buffer "^5.0.1" 205 | sha.js "^2.4.8" 206 | 207 | crypt@0.0.2: 208 | version "0.0.2" 209 | resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" 210 | integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= 211 | 212 | crypto-browserify@^3.11.0: 213 | version "3.12.0" 214 | resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" 215 | integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== 216 | dependencies: 217 | browserify-cipher "^1.0.0" 218 | browserify-sign "^4.0.0" 219 | create-ecdh "^4.0.0" 220 | create-hash "^1.1.0" 221 | create-hmac "^1.1.0" 222 | diffie-hellman "^5.0.0" 223 | inherits "^2.0.1" 224 | pbkdf2 "^3.0.3" 225 | public-encrypt "^4.0.0" 226 | randombytes "^2.0.0" 227 | randomfill "^1.0.3" 228 | 229 | des.js@^1.0.0: 230 | version "1.0.1" 231 | resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" 232 | integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== 233 | dependencies: 234 | inherits "^2.0.1" 235 | minimalistic-assert "^1.0.0" 236 | 237 | diffie-hellman@^5.0.0: 238 | version "5.0.3" 239 | resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" 240 | integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== 241 | dependencies: 242 | bn.js "^4.1.0" 243 | miller-rabin "^4.0.0" 244 | randombytes "^2.0.0" 245 | 246 | domain-browser@^1.1.1: 247 | version "1.2.0" 248 | resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" 249 | integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== 250 | 251 | elliptic@^6.5.3, elliptic@^6.5.4: 252 | version "6.6.0" 253 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210" 254 | integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA== 255 | dependencies: 256 | bn.js "^4.11.9" 257 | brorand "^1.1.0" 258 | hash.js "^1.0.0" 259 | hmac-drbg "^1.0.1" 260 | inherits "^2.0.4" 261 | minimalistic-assert "^1.0.1" 262 | minimalistic-crypto-utils "^1.0.1" 263 | 264 | events@^3.0.0: 265 | version "3.2.0" 266 | resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" 267 | integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== 268 | 269 | evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: 270 | version "1.0.3" 271 | resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" 272 | integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== 273 | dependencies: 274 | md5.js "^1.3.4" 275 | safe-buffer "^5.1.1" 276 | 277 | feather-icons@^4.28.0: 278 | version "4.28.0" 279 | resolved "https://registry.yarnpkg.com/feather-icons/-/feather-icons-4.28.0.tgz#e1892a401fe12c4559291770ff6e68b0168e760f" 280 | integrity sha512-gRdqKESXRBUZn6Nl0VBq2wPHKRJgZz7yblrrc2lYsS6odkNFDnA4bqvrlEVRUPjE1tFax+0TdbJKZ31ziJuzjg== 281 | dependencies: 282 | classnames "^2.2.5" 283 | core-js "^3.1.3" 284 | 285 | growly@^1.3.0: 286 | version "1.3.0" 287 | resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" 288 | integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= 289 | 290 | hash-base@^3.0.0: 291 | version "3.1.0" 292 | resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" 293 | integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== 294 | dependencies: 295 | inherits "^2.0.4" 296 | readable-stream "^3.6.0" 297 | safe-buffer "^5.2.0" 298 | 299 | hash.js@^1.0.0, hash.js@^1.0.3: 300 | version "1.1.7" 301 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" 302 | integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== 303 | dependencies: 304 | inherits "^2.0.3" 305 | minimalistic-assert "^1.0.1" 306 | 307 | hmac-drbg@^1.0.1: 308 | version "1.0.1" 309 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" 310 | integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= 311 | dependencies: 312 | hash.js "^1.0.3" 313 | minimalistic-assert "^1.0.0" 314 | minimalistic-crypto-utils "^1.0.1" 315 | 316 | https-browserify@^1.0.0: 317 | version "1.0.0" 318 | resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" 319 | integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= 320 | 321 | ieee754@^1.1.4: 322 | version "1.2.1" 323 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 324 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 325 | 326 | inherits@2.0.1: 327 | version "2.0.1" 328 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" 329 | integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= 330 | 331 | inherits@2.0.3: 332 | version "2.0.3" 333 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 334 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= 335 | 336 | inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: 337 | version "2.0.4" 338 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 339 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 340 | 341 | is-buffer@~1.1.6: 342 | version "1.1.6" 343 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 344 | integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== 345 | 346 | is-docker@^2.0.0: 347 | version "2.1.1" 348 | resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" 349 | integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== 350 | 351 | is-wsl@^2.2.0: 352 | version "2.2.0" 353 | resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" 354 | integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== 355 | dependencies: 356 | is-docker "^2.0.0" 357 | 358 | isarray@^1.0.0, isarray@~1.0.0: 359 | version "1.0.0" 360 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 361 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 362 | 363 | isexe@^2.0.0: 364 | version "2.0.0" 365 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 366 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 367 | 368 | lru-cache@^6.0.0: 369 | version "6.0.0" 370 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 371 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 372 | dependencies: 373 | yallist "^4.0.0" 374 | 375 | md5.js@^1.3.4: 376 | version "1.3.5" 377 | resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" 378 | integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== 379 | dependencies: 380 | hash-base "^3.0.0" 381 | inherits "^2.0.1" 382 | safe-buffer "^5.1.2" 383 | 384 | md5@^2.3.0: 385 | version "2.3.0" 386 | resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" 387 | integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== 388 | dependencies: 389 | charenc "0.0.2" 390 | crypt "0.0.2" 391 | is-buffer "~1.1.6" 392 | 393 | miller-rabin@^4.0.0: 394 | version "4.0.1" 395 | resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" 396 | integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== 397 | dependencies: 398 | bn.js "^4.0.0" 399 | brorand "^1.0.1" 400 | 401 | minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: 402 | version "1.0.1" 403 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" 404 | integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== 405 | 406 | minimalistic-crypto-utils@^1.0.1: 407 | version "1.0.1" 408 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" 409 | integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= 410 | 411 | nanoid@^2.1.0: 412 | version "2.1.11" 413 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" 414 | integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA== 415 | 416 | node-libs-browser@^2.2.1: 417 | version "2.2.1" 418 | resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" 419 | integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== 420 | dependencies: 421 | assert "^1.1.1" 422 | browserify-zlib "^0.2.0" 423 | buffer "^4.3.0" 424 | console-browserify "^1.1.0" 425 | constants-browserify "^1.0.0" 426 | crypto-browserify "^3.11.0" 427 | domain-browser "^1.1.1" 428 | events "^3.0.0" 429 | https-browserify "^1.0.0" 430 | os-browserify "^0.3.0" 431 | path-browserify "0.0.1" 432 | process "^0.11.10" 433 | punycode "^1.2.4" 434 | querystring-es3 "^0.2.0" 435 | readable-stream "^2.3.3" 436 | stream-browserify "^2.0.1" 437 | stream-http "^2.7.2" 438 | string_decoder "^1.0.0" 439 | timers-browserify "^2.0.4" 440 | tty-browserify "0.0.0" 441 | url "^0.11.0" 442 | util "^0.11.0" 443 | vm-browserify "^1.0.1" 444 | 445 | node-notifier@^9.0.0: 446 | version "9.0.0" 447 | resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-9.0.0.tgz#46c5bbecbb796d4a803f646cea5bc91403f2ff38" 448 | integrity sha512-SkwNwGnMMlSPrcoeH4CSo9XyWe72acAHEJGDdPdB+CyBVHsIYaTQ4U/1wk3URsyzC75xZLg2vzU2YaALlqDF1Q== 449 | dependencies: 450 | growly "^1.3.0" 451 | is-wsl "^2.2.0" 452 | semver "^7.3.2" 453 | shellwords "^0.1.1" 454 | uuid "^8.3.0" 455 | which "^2.0.2" 456 | 457 | object-assign@^4.1.1: 458 | version "4.1.1" 459 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 460 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 461 | 462 | os-browserify@^0.3.0: 463 | version "0.3.0" 464 | resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" 465 | integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= 466 | 467 | pako@~1.0.5: 468 | version "1.0.11" 469 | resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" 470 | integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== 471 | 472 | parse-asn1@^5.0.0, parse-asn1@^5.1.6: 473 | version "5.1.6" 474 | resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" 475 | integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== 476 | dependencies: 477 | asn1.js "^5.2.0" 478 | browserify-aes "^1.0.0" 479 | evp_bytestokey "^1.0.0" 480 | pbkdf2 "^3.0.3" 481 | safe-buffer "^5.1.1" 482 | 483 | path-browserify@0.0.1: 484 | version "0.0.1" 485 | resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" 486 | integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== 487 | 488 | pbkdf2@^3.0.3: 489 | version "3.1.1" 490 | resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" 491 | integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== 492 | dependencies: 493 | create-hash "^1.1.2" 494 | create-hmac "^1.1.4" 495 | ripemd160 "^2.0.1" 496 | safe-buffer "^5.0.1" 497 | sha.js "^2.4.8" 498 | 499 | process-nextick-args@~2.0.0: 500 | version "2.0.1" 501 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 502 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 503 | 504 | process@^0.11.10: 505 | version "0.11.10" 506 | resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" 507 | integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= 508 | 509 | public-encrypt@^4.0.0: 510 | version "4.0.3" 511 | resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" 512 | integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== 513 | dependencies: 514 | bn.js "^4.1.0" 515 | browserify-rsa "^4.0.0" 516 | create-hash "^1.1.0" 517 | parse-asn1 "^5.0.0" 518 | randombytes "^2.0.1" 519 | safe-buffer "^5.1.2" 520 | 521 | punycode@1.3.2: 522 | version "1.3.2" 523 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" 524 | integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= 525 | 526 | punycode@^1.2.4: 527 | version "1.4.1" 528 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" 529 | integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= 530 | 531 | querystring-es3@^0.2.0: 532 | version "0.2.1" 533 | resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" 534 | integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= 535 | 536 | querystring@0.2.0: 537 | version "0.2.0" 538 | resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" 539 | integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= 540 | 541 | querystringify@^2.1.1: 542 | version "2.2.0" 543 | resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" 544 | integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== 545 | 546 | randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: 547 | version "2.1.0" 548 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 549 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 550 | dependencies: 551 | safe-buffer "^5.1.0" 552 | 553 | randomcolor@^0.6.2: 554 | version "0.6.2" 555 | resolved "https://registry.yarnpkg.com/randomcolor/-/randomcolor-0.6.2.tgz#7a57362ae1a1278439aeed2c15e5deb8ea33f56d" 556 | integrity sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A== 557 | 558 | randomfill@^1.0.3: 559 | version "1.0.4" 560 | resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" 561 | integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== 562 | dependencies: 563 | randombytes "^2.0.5" 564 | safe-buffer "^5.1.0" 565 | 566 | readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6: 567 | version "2.3.7" 568 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" 569 | integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 570 | dependencies: 571 | core-util-is "~1.0.0" 572 | inherits "~2.0.3" 573 | isarray "~1.0.0" 574 | process-nextick-args "~2.0.0" 575 | safe-buffer "~5.1.1" 576 | string_decoder "~1.1.1" 577 | util-deprecate "~1.0.1" 578 | 579 | readable-stream@^3.6.0: 580 | version "3.6.0" 581 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" 582 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== 583 | dependencies: 584 | inherits "^2.0.3" 585 | string_decoder "^1.1.1" 586 | util-deprecate "^1.0.1" 587 | 588 | readable-stream@^3.6.2: 589 | version "3.6.2" 590 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" 591 | integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== 592 | dependencies: 593 | inherits "^2.0.3" 594 | string_decoder "^1.1.1" 595 | util-deprecate "^1.0.1" 596 | 597 | readline-sync@^1.4.7: 598 | version "1.4.10" 599 | resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b" 600 | integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw== 601 | 602 | requires-port@^1.0.0: 603 | version "1.0.0" 604 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 605 | integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= 606 | 607 | ripemd160@^2.0.0, ripemd160@^2.0.1: 608 | version "2.0.2" 609 | resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" 610 | integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== 611 | dependencies: 612 | hash-base "^3.0.0" 613 | inherits "^2.0.1" 614 | 615 | safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: 616 | version "5.2.1" 617 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 618 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 619 | 620 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 621 | version "5.1.2" 622 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 623 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 624 | 625 | safer-buffer@^2.1.0: 626 | version "2.1.2" 627 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 628 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 629 | 630 | semver@^7.3.2: 631 | version "7.5.3" 632 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" 633 | integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== 634 | dependencies: 635 | lru-cache "^6.0.0" 636 | 637 | setimmediate@^1.0.4: 638 | version "1.0.5" 639 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 640 | integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= 641 | 642 | sha.js@^2.4.0, sha.js@^2.4.8: 643 | version "2.4.11" 644 | resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" 645 | integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== 646 | dependencies: 647 | inherits "^2.0.1" 648 | safe-buffer "^5.0.1" 649 | 650 | shadow-cljs-jar@1.3.2: 651 | version "1.3.2" 652 | resolved "https://registry.yarnpkg.com/shadow-cljs-jar/-/shadow-cljs-jar-1.3.2.tgz#97273afe1747b6a2311917c1c88d9e243c81957b" 653 | integrity sha512-XmeffAZHv8z7451kzeq9oKh8fh278Ak+UIOGGrapyqrFBB773xN8vMQ3O7J7TYLnb9BUwcqadKkmgaq7q6fhZg== 654 | 655 | shadow-cljs@^2.11.18: 656 | version "2.11.18" 657 | resolved "https://registry.yarnpkg.com/shadow-cljs/-/shadow-cljs-2.11.18.tgz#f83fe776c9001afdf92611e6bef6da8aed926aab" 658 | integrity sha512-7EAXl1xk2GjhViUeexn7cqAPx0lkEl2J40nAbPPCrAbfLfOWn5tjV4P3Be6IqTInSHMx04tFxDRV+0xFdIhl5A== 659 | dependencies: 660 | node-libs-browser "^2.2.1" 661 | readline-sync "^1.4.7" 662 | shadow-cljs-jar "1.3.2" 663 | source-map-support "^0.4.15" 664 | which "^1.3.1" 665 | ws "^3.0.0" 666 | 667 | shellwords@^0.1.1: 668 | version "0.1.1" 669 | resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" 670 | integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== 671 | 672 | shortid@^2.2.16: 673 | version "2.2.16" 674 | resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.16.tgz#b742b8f0cb96406fd391c76bfc18a67a57fe5608" 675 | integrity sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g== 676 | dependencies: 677 | nanoid "^2.1.0" 678 | 679 | source-map-support@^0.4.15: 680 | version "0.4.18" 681 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" 682 | integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== 683 | dependencies: 684 | source-map "^0.5.6" 685 | 686 | source-map-support@^0.5.19: 687 | version "0.5.19" 688 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" 689 | integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== 690 | dependencies: 691 | buffer-from "^1.0.0" 692 | source-map "^0.6.0" 693 | 694 | source-map@^0.5.6: 695 | version "0.5.7" 696 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 697 | integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= 698 | 699 | source-map@^0.6.0: 700 | version "0.6.1" 701 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 702 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 703 | 704 | stream-browserify@^2.0.1: 705 | version "2.0.2" 706 | resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" 707 | integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== 708 | dependencies: 709 | inherits "~2.0.1" 710 | readable-stream "^2.0.2" 711 | 712 | stream-http@^2.7.2: 713 | version "2.8.3" 714 | resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" 715 | integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== 716 | dependencies: 717 | builtin-status-codes "^3.0.0" 718 | inherits "^2.0.1" 719 | readable-stream "^2.3.6" 720 | to-arraybuffer "^1.0.0" 721 | xtend "^4.0.0" 722 | 723 | string_decoder@^1.0.0, string_decoder@^1.1.1: 724 | version "1.3.0" 725 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" 726 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 727 | dependencies: 728 | safe-buffer "~5.2.0" 729 | 730 | string_decoder@~1.1.1: 731 | version "1.1.1" 732 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 733 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 734 | dependencies: 735 | safe-buffer "~5.1.0" 736 | 737 | timers-browserify@^2.0.4: 738 | version "2.0.12" 739 | resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" 740 | integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== 741 | dependencies: 742 | setimmediate "^1.0.4" 743 | 744 | to-arraybuffer@^1.0.0: 745 | version "1.0.1" 746 | resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" 747 | integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= 748 | 749 | tty-browserify@0.0.0: 750 | version "0.0.0" 751 | resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" 752 | integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= 753 | 754 | ultron@~1.1.0: 755 | version "1.1.1" 756 | resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" 757 | integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== 758 | 759 | url-parse@^1.5.9: 760 | version "1.5.9" 761 | resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.9.tgz#05ff26484a0b5e4040ac64dcee4177223d74675e" 762 | integrity sha512-HpOvhKBvre8wYez+QhHcYiVvVmeF6DVnuSOOPhe3cTum3BnqHhvKaZm8FU5yTiOu/Jut2ZpB2rA/SbBA1JIGlQ== 763 | dependencies: 764 | querystringify "^2.1.1" 765 | requires-port "^1.0.0" 766 | 767 | url@^0.11.0: 768 | version "0.11.0" 769 | resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" 770 | integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= 771 | dependencies: 772 | punycode "1.3.2" 773 | querystring "0.2.0" 774 | 775 | util-deprecate@^1.0.1, util-deprecate@~1.0.1: 776 | version "1.0.2" 777 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 778 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 779 | 780 | util@0.10.3: 781 | version "0.10.3" 782 | resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" 783 | integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= 784 | dependencies: 785 | inherits "2.0.1" 786 | 787 | util@^0.11.0: 788 | version "0.11.1" 789 | resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" 790 | integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== 791 | dependencies: 792 | inherits "2.0.3" 793 | 794 | uuid@^8.3.0: 795 | version "8.3.2" 796 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" 797 | integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== 798 | 799 | vm-browserify@^1.0.1: 800 | version "1.1.2" 801 | resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" 802 | integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== 803 | 804 | which@^1.3.1: 805 | version "1.3.1" 806 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 807 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 808 | dependencies: 809 | isexe "^2.0.0" 810 | 811 | which@^2.0.2: 812 | version "2.0.2" 813 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 814 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 815 | dependencies: 816 | isexe "^2.0.0" 817 | 818 | ws@^3.0.0: 819 | version "3.3.3" 820 | resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" 821 | integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== 822 | dependencies: 823 | async-limiter "~1.0.0" 824 | safe-buffer "~5.1.0" 825 | ultron "~1.1.0" 826 | 827 | ws@^7.5.10: 828 | version "7.5.10" 829 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" 830 | integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== 831 | 832 | xtend@^4.0.0: 833 | version "4.0.2" 834 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 835 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 836 | 837 | yallist@^4.0.0: 838 | version "4.0.0" 839 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 840 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 841 | --------------------------------------------------------------------------------