├── .clj-kondo └── config.edn ├── .github ├── FUNDING.yml └── workflows │ └── test.yml ├── .gitignore ├── CHANGELOG.md ├── README.adoc ├── deps.edn ├── karma.conf.js ├── package-lock.json ├── package.json ├── pom.xml ├── project.clj ├── resources └── clj-kondo.exports │ └── com.wsscode │ └── async │ └── config.edn ├── script ├── release └── test ├── shadow-cljs.edn ├── src └── com │ └── wsscode │ └── async │ ├── async_clj.clj │ ├── async_cljs.clj │ ├── async_cljs.cljs │ ├── coll.cljc │ └── processing.cljc └── test └── com └── wsscode └── async ├── async_clj_test.clj ├── async_cljs_test.cljs ├── coll_test.cljc └── processing_test.cljc /.clj-kondo/config.edn: -------------------------------------------------------------------------------- 1 | {:lint-as {com.fulcrologic.guardrails.core/>def clojure.spec.alpha/def 2 | com.fulcrologic.guardrails.core/>defn clojure.core/defn 3 | com.wsscode.async.async-clj/deftest-async clojure.test/deftest 4 | com.wsscode.async.async-clj/go-try-stream clojure.core/let 5 | com.wsscode.async.async-clj/let-chan clojure.core/let 6 | com.wsscode.async.async-clj/let-chan* clojure.core/let 7 | com.wsscode.async.async-cljs/deftest-async clojure.test/deftest 8 | com.wsscode.async.async-cljs/go-try-stream clojure.core/let 9 | com.wsscode.async.async-cljs/let-chan clojure.core/let 10 | com.wsscode.async.async-cljs/let-chan* clojure.core/let 11 | nubank.workspaces.core/defcard clojure.core/def} 12 | :linters {:unsorted-required-namespaces {:level :warning} 13 | :missing-else-branch {:level :off} 14 | :unresolved-symbol {:exclude [(com.wsscode.async.async-cljs/go-try-stream [e])]} 15 | :consistent-alias {:level :warning 16 | :aliases {com.wsscode.async.processing wap}} 17 | :unused-namespace {:level :warning 18 | :exclude [com.fulcrologic.guardrails.core]} 19 | :unused-referred-var {:level :warning 20 | :exclude {com.wsscode.async.async-clj [let-chan let-chan* 21 | go go-catch go-promise 22 | def >defn >fdef => | <- ?] 27 | clojure.test [deftest is are run-tests testing] 28 | cljs.test [deftest is are run-tests testing]}}}} 29 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: wsscode 2 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: DeLaGuardo/setup-clj-kondo@master 10 | with: 11 | version: '2020.04.05' 12 | 13 | - uses: DeLaGuardo/setup-clojure@master 14 | with: 15 | tools-deps: '1.10.1.469' 16 | 17 | - uses: actions/checkout@v1 18 | 19 | - name: Cache dependencies lint 20 | run: echo "$(clj-kondo --lint \"$(clojure -Spath)\")" 21 | 22 | - name: Run linter 23 | run: clj-kondo --lint src 24 | 25 | test-clj: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - name: Check out Git repository 29 | uses: actions/checkout@v1 30 | 31 | - uses: DeLaGuardo/setup-clojure@master 32 | with: 33 | tools-deps: '1.10.1.469' 34 | 35 | - name: Cache maven 36 | uses: actions/cache@v1 37 | with: 38 | path: ~/.m2 39 | key: m2-${{ hashFiles('deps.edn') }} 40 | restore-keys: | 41 | m2- 42 | 43 | - name: Test 44 | run: ./script/test 45 | 46 | test-cljs: 47 | runs-on: ubuntu-latest 48 | steps: 49 | - name: Check out Git repository 50 | uses: actions/checkout@v1 51 | 52 | - uses: DeLaGuardo/setup-clojure@master 53 | with: 54 | tools-deps: '1.10.1.469' 55 | 56 | - name: Cache maven 57 | uses: actions/cache@v1 58 | with: 59 | path: ~/.m2 60 | key: m2-${{ hashFiles('deps.edn') }} 61 | restore-keys: | 62 | m2- 63 | 64 | - name: Cache node_modules 65 | uses: actions/cache@v1 66 | with: 67 | path: node_modules 68 | key: node_modules-${{ hashFiles('package-lock.json') }} 69 | restore-keys: | 70 | node_modules- 71 | 72 | - name: Use Node.js 12.x 73 | uses: actions/setup-node@v1 74 | with: 75 | node-version: '12.x' 76 | 77 | - name: NPM Install 78 | run: npm install 79 | 80 | - name: Compile CLJS tests 81 | run: npx shadow-cljs compile ci 82 | 83 | - name: Run CLJS tests 84 | run: npx karma start --single-run 85 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Clojure template 3 | pom.xml.asc 4 | *.jar 5 | *.class 6 | /lib/ 7 | /classes/ 8 | /target/ 9 | /checkouts/ 10 | .lein-deps-sum 11 | .lein-repl-history 12 | .lein-plugins/ 13 | .lein-failures 14 | .nrepl-port 15 | .cpcache/ 16 | .shadow-cljs 17 | /node_modules 18 | /resources/public/js 19 | .clj-kondo/.cache 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## 2021.01.15 4 | - Add `coll` namespace for collection utils with async process 5 | 6 | ## 2020.01.14 7 | - Provide clj-kondo exports for lint 8 | 9 | ## 1.0.11 10 | - Release using Leiningen to get cljdoc back to work. 11 | 12 | ## 1.0.10 13 | - BREAKING: use namespaced options in `pulling-retry` 14 | - Support simpler interface on `pulling-retry` - `(pulling-retry doner-check (ops))` 15 | 16 | ## 1.0.9 -- Broken interface, avoid using this version 17 | - Add `timeout-chan` 18 | - Add `pulling-retry` 19 | 20 | ## 1.0.8 21 | - Fixes `go-loop` wrappers, thanks clj-kondo! 22 | 23 | ## 1.0.7 24 | - Change `await!` to skip messages that already have a reply 25 | 26 | ## 1.0.6 27 | - Important bug fix: `1.0.5` introduced an error by requiring `clojure.core.async` 28 | instead of `cljs.core.async` for macros, this could break some builds in very 29 | unexpected ways, this update is highly encouraged. 30 | 31 | ## 1.0.5 - BROKEN, DON'T USE 32 | - Add `go-try-stream` helper 33 | 34 | ## 1.0.4 35 | - Add `go-loop` convenience method 36 | - Add `com.wsscode.async.processing` namespace 37 | - Add `deftest-async` on the clojure side 38 | 39 | ## 1.0.3 40 | - Add `thread` helpers in the `clj` side 41 | 42 | ## 1.0.2 43 | - Fix `go-promise` on both clj and cljs to allow returning `false` 44 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = core.async helpers 2 | :toc: 3 | :toc-placement!: 4 | 5 | ifdef::env-github,env-cljdoc[] 6 | :tip-caption: :bulb: 7 | :note-caption: :information_source: 8 | :important-caption: :heavy_exclamation_mark: 9 | :caution-caption: :fire: 10 | :warning-caption: :warning: 11 | endif::[] 12 | 13 | image:https://img.shields.io/clojars/v/com.wsscode/async.svg[link=https://clojars.org/com.wsscode/async] 14 | image:https://cljdoc.xyz/badge/com.wsscode/async["cljdoc", link="https://cljdoc.xyz/d/com.wsscode/async/CURRENT"] 15 | image:https://github.com/wilkerlucio/wsscode-async/workflows/Test/badge.svg?branch=master["Test"] 16 | 17 | `Core.async` is the standard way to handle async features in Clojure and ClojureScript programs. 18 | 19 | Although core.async is built upon link:https://en.wikipedia.org/wiki/Communicating_sequential_processes[CSP], 20 | often (specially in CLJS) is desired to have something that's more like link:https://en.wikipedia.org/wiki/Futures_and_promises[Promises/Futures]. 21 | 22 | Core.async provides a `promise-chan`, which is a channel that has a promise-like semantic: 23 | after realization, any read on it will keep returning the same value. That's helpful but 24 | this doesn't cover the problem of error propagation, in a promise system it's expected 25 | that errors can flow up to be captured by some higher level code. 26 | 27 | This library provide some helpers to deal with this problem, and also: 28 | 29 | 1. helpers to integrate with Javascript Promises in ClojureScript environments. 30 | 2. helpers to write tests using core.async and cljs.test. 31 | 3. serialized event callback handling 32 | 4. `ID` based async callbacks 33 | 5. helpers for timeouts using error handling 34 | 6. helpers to pulling retry operations 35 | 36 | toc::[] 37 | 38 | == Setup 39 | 40 | This library uses separated namespaces for Clojure and ClojureScript, when using the 41 | Clojure side, use the namespace `com.wsscode.async.async-clj`, and for ClojureScript 42 | use `com.wsscode.async.async-cljs`. Unless pointed otherwise, the features on both 43 | namespaces are the same. 44 | 45 | If you want to use this with Clojure Common files, you can use the require like this: 46 | 47 | [source,clojure] 48 | ---- 49 | (ns my-ns 50 | (:require [#?(:clj com.wsscode.async.async-clj 51 | :cljs com.wsscode.async.async-cljs) 52 | :as wa 53 | :refer [go-promise 69 | (go-promise 70 | (/ x y))) 71 | 72 | (defn run [d] 73 | (go-promise 74 | (try 75 | ; <2> 76 | ( 3 <3> 82 | ( "ERROR" <4> 83 | ) 84 | ---- 85 | 86 | <1> `go-promise` is similar to `go`, but will return a promise-channel, so in case this result gets 87 | passed to multiple readers, all of them will get the realized value or error. This also 88 | wraps the block in a try/catch, so if some exception happens it will get returned as the channel value. 89 | 90 | <2> ` propagate value back 94 | 95 | <4> error propagated from async-divide trying to divide by zero 96 | 97 | By following this pattern of error capture and send, this system ends up working in the 98 | same ways you would expect a promise, all while still in the same `go` blocks, making 99 | it compatible with standard core.async functionality. Later we will also talk about how 100 | to integrate with Javascript Promises in this system. 101 | 102 | === Nil returns 103 | 104 | Another difference when using `go-promise` is that different from regular `go`, you can 105 | return `nil` as a value. Since the promise will always return the same value, a `nil` 106 | is not ambiguous. 107 | 108 | NOTE: In the implementation side, `go-promise` check if the value returned is `nil`, and 109 | if so it just closes the channel, making it an effective `nil` value. 110 | 111 | === Extra takers 112 | 113 | We just saw the helper ` 154 | (go-promise 155 | (-> (js/fetch "/") Read the index text of the current domain, note we are waiting for two different 161 | promises in this example, the first one for the fetch headers and the second to get the 162 | body text. 163 | 164 | NOTE: the way ` (do-operation e) (do-operation e) (do-operation e) (do-operation e) = 1.5.0 < 2", 882 | "toidentifier": "1.0.0" 883 | }, 884 | "dependencies": { 885 | "inherits": { 886 | "version": "2.0.3", 887 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 888 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 889 | "dev": true 890 | } 891 | } 892 | }, 893 | "http-proxy": { 894 | "version": "1.18.0", 895 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", 896 | "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", 897 | "dev": true, 898 | "requires": { 899 | "eventemitter3": "^4.0.0", 900 | "follow-redirects": "^1.0.0", 901 | "requires-port": "^1.0.0" 902 | } 903 | }, 904 | "https-browserify": { 905 | "version": "1.0.0", 906 | "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", 907 | "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" 908 | }, 909 | "iconv-lite": { 910 | "version": "0.4.24", 911 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 912 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 913 | "dev": true, 914 | "requires": { 915 | "safer-buffer": ">= 2.1.2 < 3" 916 | } 917 | }, 918 | "ieee754": { 919 | "version": "1.1.13", 920 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 921 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 922 | }, 923 | "indexof": { 924 | "version": "0.0.1", 925 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 926 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", 927 | "dev": true 928 | }, 929 | "inflight": { 930 | "version": "1.0.6", 931 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 932 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 933 | "dev": true, 934 | "requires": { 935 | "once": "^1.3.0", 936 | "wrappy": "1" 937 | } 938 | }, 939 | "inherits": { 940 | "version": "2.0.1", 941 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 942 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 943 | }, 944 | "is-binary-path": { 945 | "version": "2.1.0", 946 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 947 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 948 | "dev": true, 949 | "requires": { 950 | "binary-extensions": "^2.0.0" 951 | } 952 | }, 953 | "is-extglob": { 954 | "version": "2.1.1", 955 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 956 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 957 | "dev": true 958 | }, 959 | "is-fullwidth-code-point": { 960 | "version": "3.0.0", 961 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 962 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 963 | "dev": true 964 | }, 965 | "is-glob": { 966 | "version": "4.0.1", 967 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 968 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 969 | "dev": true, 970 | "requires": { 971 | "is-extglob": "^2.1.1" 972 | } 973 | }, 974 | "is-number": { 975 | "version": "7.0.0", 976 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 977 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 978 | "dev": true 979 | }, 980 | "isarray": { 981 | "version": "1.0.0", 982 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 983 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 984 | }, 985 | "isbinaryfile": { 986 | "version": "4.0.6", 987 | "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz", 988 | "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==", 989 | "dev": true 990 | }, 991 | "isexe": { 992 | "version": "2.0.0", 993 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 994 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 995 | }, 996 | "jsonfile": { 997 | "version": "4.0.0", 998 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 999 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 1000 | "dev": true, 1001 | "requires": { 1002 | "graceful-fs": "^4.1.6" 1003 | } 1004 | }, 1005 | "karma": { 1006 | "version": "5.0.3", 1007 | "resolved": "https://registry.npmjs.org/karma/-/karma-5.0.3.tgz", 1008 | "integrity": "sha512-436fnV2PU7i4+dbc5NgIBnDfkCS8exSDkv8m33ttKTRd1OWSjZEdUM5tnEzQBC48Zs9S/bwM1oTi+WgLL935Og==", 1009 | "dev": true, 1010 | "requires": { 1011 | "body-parser": "^1.16.1", 1012 | "braces": "^3.0.2", 1013 | "chokidar": "^3.0.0", 1014 | "colors": "^1.1.0", 1015 | "connect": "^3.6.0", 1016 | "di": "^0.0.1", 1017 | "dom-serialize": "^2.2.0", 1018 | "flatted": "^2.0.0", 1019 | "glob": "^7.1.1", 1020 | "graceful-fs": "^4.1.2", 1021 | "http-proxy": "^1.13.0", 1022 | "isbinaryfile": "^4.0.2", 1023 | "lodash": "^4.17.14", 1024 | "log4js": "^4.0.0", 1025 | "mime": "^2.3.1", 1026 | "minimatch": "^3.0.2", 1027 | "qjobs": "^1.1.4", 1028 | "range-parser": "^1.2.0", 1029 | "rimraf": "^2.6.0", 1030 | "socket.io": "2.1.1", 1031 | "source-map": "^0.6.1", 1032 | "tmp": "0.0.33", 1033 | "ua-parser-js": "0.7.21", 1034 | "yargs": "^15.3.1" 1035 | }, 1036 | "dependencies": { 1037 | "source-map": { 1038 | "version": "0.6.1", 1039 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1040 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1041 | "dev": true 1042 | } 1043 | } 1044 | }, 1045 | "karma-chrome-launcher": { 1046 | "version": "3.1.0", 1047 | "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", 1048 | "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", 1049 | "dev": true, 1050 | "requires": { 1051 | "which": "^1.2.1" 1052 | } 1053 | }, 1054 | "karma-cljs-test": { 1055 | "version": "0.1.0", 1056 | "resolved": "https://registry.npmjs.org/karma-cljs-test/-/karma-cljs-test-0.1.0.tgz", 1057 | "integrity": "sha1-y4YF7w4R+ab20o9Wul298m84mSM=", 1058 | "dev": true 1059 | }, 1060 | "locate-path": { 1061 | "version": "5.0.0", 1062 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1063 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1064 | "dev": true, 1065 | "requires": { 1066 | "p-locate": "^4.1.0" 1067 | } 1068 | }, 1069 | "lodash": { 1070 | "version": "4.17.15", 1071 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 1072 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 1073 | "dev": true 1074 | }, 1075 | "log4js": { 1076 | "version": "4.5.1", 1077 | "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", 1078 | "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", 1079 | "dev": true, 1080 | "requires": { 1081 | "date-format": "^2.0.0", 1082 | "debug": "^4.1.1", 1083 | "flatted": "^2.0.0", 1084 | "rfdc": "^1.1.4", 1085 | "streamroller": "^1.0.6" 1086 | }, 1087 | "dependencies": { 1088 | "debug": { 1089 | "version": "4.1.1", 1090 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 1091 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 1092 | "dev": true, 1093 | "requires": { 1094 | "ms": "^2.1.1" 1095 | } 1096 | }, 1097 | "ms": { 1098 | "version": "2.1.2", 1099 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1100 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1101 | "dev": true 1102 | } 1103 | } 1104 | }, 1105 | "md5.js": { 1106 | "version": "1.3.5", 1107 | "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", 1108 | "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", 1109 | "requires": { 1110 | "hash-base": "^3.0.0", 1111 | "inherits": "^2.0.1", 1112 | "safe-buffer": "^5.1.2" 1113 | } 1114 | }, 1115 | "media-typer": { 1116 | "version": "0.3.0", 1117 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1118 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 1119 | "dev": true 1120 | }, 1121 | "miller-rabin": { 1122 | "version": "4.0.1", 1123 | "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", 1124 | "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", 1125 | "requires": { 1126 | "bn.js": "^4.0.0", 1127 | "brorand": "^1.0.1" 1128 | } 1129 | }, 1130 | "mime": { 1131 | "version": "2.4.4", 1132 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", 1133 | "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", 1134 | "dev": true 1135 | }, 1136 | "mime-db": { 1137 | "version": "1.44.0", 1138 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 1139 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", 1140 | "dev": true 1141 | }, 1142 | "mime-types": { 1143 | "version": "2.1.27", 1144 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 1145 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 1146 | "dev": true, 1147 | "requires": { 1148 | "mime-db": "1.44.0" 1149 | } 1150 | }, 1151 | "minimalistic-assert": { 1152 | "version": "1.0.1", 1153 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 1154 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" 1155 | }, 1156 | "minimalistic-crypto-utils": { 1157 | "version": "1.0.1", 1158 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 1159 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" 1160 | }, 1161 | "minimatch": { 1162 | "version": "3.0.4", 1163 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1164 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1165 | "dev": true, 1166 | "requires": { 1167 | "brace-expansion": "^1.1.7" 1168 | } 1169 | }, 1170 | "minimist": { 1171 | "version": "0.0.8", 1172 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1173 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 1174 | }, 1175 | "mkdirp": { 1176 | "version": "0.5.1", 1177 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1178 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1179 | "requires": { 1180 | "minimist": "0.0.8" 1181 | } 1182 | }, 1183 | "ms": { 1184 | "version": "2.0.0", 1185 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1186 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1187 | "dev": true 1188 | }, 1189 | "negotiator": { 1190 | "version": "0.6.2", 1191 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 1192 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", 1193 | "dev": true 1194 | }, 1195 | "node-libs-browser": { 1196 | "version": "2.2.1", 1197 | "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", 1198 | "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", 1199 | "requires": { 1200 | "assert": "^1.1.1", 1201 | "browserify-zlib": "^0.2.0", 1202 | "buffer": "^4.3.0", 1203 | "console-browserify": "^1.1.0", 1204 | "constants-browserify": "^1.0.0", 1205 | "crypto-browserify": "^3.11.0", 1206 | "domain-browser": "^1.1.1", 1207 | "events": "^3.0.0", 1208 | "https-browserify": "^1.0.0", 1209 | "os-browserify": "^0.3.0", 1210 | "path-browserify": "0.0.1", 1211 | "process": "^0.11.10", 1212 | "punycode": "^1.2.4", 1213 | "querystring-es3": "^0.2.0", 1214 | "readable-stream": "^2.3.3", 1215 | "stream-browserify": "^2.0.1", 1216 | "stream-http": "^2.7.2", 1217 | "string_decoder": "^1.0.0", 1218 | "timers-browserify": "^2.0.4", 1219 | "tty-browserify": "0.0.0", 1220 | "url": "^0.11.0", 1221 | "util": "^0.11.0", 1222 | "vm-browserify": "^1.0.1" 1223 | } 1224 | }, 1225 | "normalize-path": { 1226 | "version": "3.0.0", 1227 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1228 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1229 | "dev": true 1230 | }, 1231 | "object-assign": { 1232 | "version": "4.1.1", 1233 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1234 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1235 | }, 1236 | "object-component": { 1237 | "version": "0.0.3", 1238 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", 1239 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", 1240 | "dev": true 1241 | }, 1242 | "on-finished": { 1243 | "version": "2.3.0", 1244 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1245 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1246 | "dev": true, 1247 | "requires": { 1248 | "ee-first": "1.1.1" 1249 | } 1250 | }, 1251 | "once": { 1252 | "version": "1.4.0", 1253 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1254 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1255 | "dev": true, 1256 | "requires": { 1257 | "wrappy": "1" 1258 | } 1259 | }, 1260 | "os-browserify": { 1261 | "version": "0.3.0", 1262 | "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", 1263 | "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" 1264 | }, 1265 | "os-tmpdir": { 1266 | "version": "1.0.2", 1267 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1268 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 1269 | "dev": true 1270 | }, 1271 | "p-limit": { 1272 | "version": "2.3.0", 1273 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1274 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1275 | "dev": true, 1276 | "requires": { 1277 | "p-try": "^2.0.0" 1278 | } 1279 | }, 1280 | "p-locate": { 1281 | "version": "4.1.0", 1282 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 1283 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 1284 | "dev": true, 1285 | "requires": { 1286 | "p-limit": "^2.2.0" 1287 | } 1288 | }, 1289 | "p-try": { 1290 | "version": "2.2.0", 1291 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1292 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1293 | "dev": true 1294 | }, 1295 | "pako": { 1296 | "version": "1.0.10", 1297 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", 1298 | "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" 1299 | }, 1300 | "parse-asn1": { 1301 | "version": "5.1.5", 1302 | "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", 1303 | "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", 1304 | "requires": { 1305 | "asn1.js": "^4.0.0", 1306 | "browserify-aes": "^1.0.0", 1307 | "create-hash": "^1.1.0", 1308 | "evp_bytestokey": "^1.0.0", 1309 | "pbkdf2": "^3.0.3", 1310 | "safe-buffer": "^5.1.1" 1311 | } 1312 | }, 1313 | "parseqs": { 1314 | "version": "0.0.5", 1315 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", 1316 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", 1317 | "dev": true, 1318 | "requires": { 1319 | "better-assert": "~1.0.0" 1320 | } 1321 | }, 1322 | "parseuri": { 1323 | "version": "0.0.5", 1324 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", 1325 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", 1326 | "dev": true, 1327 | "requires": { 1328 | "better-assert": "~1.0.0" 1329 | } 1330 | }, 1331 | "parseurl": { 1332 | "version": "1.3.3", 1333 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1334 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1335 | "dev": true 1336 | }, 1337 | "path-browserify": { 1338 | "version": "0.0.1", 1339 | "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", 1340 | "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" 1341 | }, 1342 | "path-exists": { 1343 | "version": "4.0.0", 1344 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1345 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1346 | "dev": true 1347 | }, 1348 | "path-is-absolute": { 1349 | "version": "1.0.1", 1350 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1351 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1352 | "dev": true 1353 | }, 1354 | "pbkdf2": { 1355 | "version": "3.0.17", 1356 | "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", 1357 | "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", 1358 | "requires": { 1359 | "create-hash": "^1.1.2", 1360 | "create-hmac": "^1.1.4", 1361 | "ripemd160": "^2.0.1", 1362 | "safe-buffer": "^5.0.1", 1363 | "sha.js": "^2.4.8" 1364 | } 1365 | }, 1366 | "picomatch": { 1367 | "version": "2.2.2", 1368 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 1369 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 1370 | "dev": true 1371 | }, 1372 | "process": { 1373 | "version": "0.11.10", 1374 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 1375 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" 1376 | }, 1377 | "process-nextick-args": { 1378 | "version": "2.0.1", 1379 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1380 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1381 | }, 1382 | "public-encrypt": { 1383 | "version": "4.0.3", 1384 | "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", 1385 | "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", 1386 | "requires": { 1387 | "bn.js": "^4.1.0", 1388 | "browserify-rsa": "^4.0.0", 1389 | "create-hash": "^1.1.0", 1390 | "parse-asn1": "^5.0.0", 1391 | "randombytes": "^2.0.1", 1392 | "safe-buffer": "^5.1.2" 1393 | } 1394 | }, 1395 | "punycode": { 1396 | "version": "1.4.1", 1397 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1398 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1399 | }, 1400 | "qjobs": { 1401 | "version": "1.2.0", 1402 | "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", 1403 | "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", 1404 | "dev": true 1405 | }, 1406 | "qs": { 1407 | "version": "6.7.0", 1408 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 1409 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", 1410 | "dev": true 1411 | }, 1412 | "querystring": { 1413 | "version": "0.2.0", 1414 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1415 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 1416 | }, 1417 | "querystring-es3": { 1418 | "version": "0.2.1", 1419 | "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", 1420 | "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" 1421 | }, 1422 | "randombytes": { 1423 | "version": "2.1.0", 1424 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1425 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1426 | "requires": { 1427 | "safe-buffer": "^5.1.0" 1428 | } 1429 | }, 1430 | "randomfill": { 1431 | "version": "1.0.4", 1432 | "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", 1433 | "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", 1434 | "requires": { 1435 | "randombytes": "^2.0.5", 1436 | "safe-buffer": "^5.1.0" 1437 | } 1438 | }, 1439 | "range-parser": { 1440 | "version": "1.2.1", 1441 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1442 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1443 | "dev": true 1444 | }, 1445 | "raw-body": { 1446 | "version": "2.4.0", 1447 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 1448 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 1449 | "dev": true, 1450 | "requires": { 1451 | "bytes": "3.1.0", 1452 | "http-errors": "1.7.2", 1453 | "iconv-lite": "0.4.24", 1454 | "unpipe": "1.0.0" 1455 | } 1456 | }, 1457 | "readable-stream": { 1458 | "version": "2.3.7", 1459 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1460 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1461 | "requires": { 1462 | "core-util-is": "~1.0.0", 1463 | "inherits": "~2.0.3", 1464 | "isarray": "~1.0.0", 1465 | "process-nextick-args": "~2.0.0", 1466 | "safe-buffer": "~5.1.1", 1467 | "string_decoder": "~1.1.1", 1468 | "util-deprecate": "~1.0.1" 1469 | }, 1470 | "dependencies": { 1471 | "inherits": { 1472 | "version": "2.0.4", 1473 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1474 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1475 | }, 1476 | "safe-buffer": { 1477 | "version": "5.1.2", 1478 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1479 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1480 | }, 1481 | "string_decoder": { 1482 | "version": "1.1.1", 1483 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1484 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1485 | "requires": { 1486 | "safe-buffer": "~5.1.0" 1487 | } 1488 | } 1489 | } 1490 | }, 1491 | "readdirp": { 1492 | "version": "3.4.0", 1493 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", 1494 | "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", 1495 | "dev": true, 1496 | "requires": { 1497 | "picomatch": "^2.2.1" 1498 | } 1499 | }, 1500 | "readline-sync": { 1501 | "version": "1.4.10", 1502 | "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", 1503 | "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==" 1504 | }, 1505 | "require-directory": { 1506 | "version": "2.1.1", 1507 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1508 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1509 | "dev": true 1510 | }, 1511 | "require-main-filename": { 1512 | "version": "2.0.0", 1513 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1514 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 1515 | "dev": true 1516 | }, 1517 | "requires-port": { 1518 | "version": "1.0.0", 1519 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 1520 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", 1521 | "dev": true 1522 | }, 1523 | "rfdc": { 1524 | "version": "1.1.4", 1525 | "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", 1526 | "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", 1527 | "dev": true 1528 | }, 1529 | "rimraf": { 1530 | "version": "2.7.1", 1531 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 1532 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 1533 | "dev": true, 1534 | "requires": { 1535 | "glob": "^7.1.3" 1536 | } 1537 | }, 1538 | "ripemd160": { 1539 | "version": "2.0.2", 1540 | "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", 1541 | "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", 1542 | "requires": { 1543 | "hash-base": "^3.0.0", 1544 | "inherits": "^2.0.1" 1545 | } 1546 | }, 1547 | "safe-buffer": { 1548 | "version": "5.2.0", 1549 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 1550 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 1551 | }, 1552 | "safer-buffer": { 1553 | "version": "2.1.2", 1554 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1555 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1556 | "dev": true 1557 | }, 1558 | "set-blocking": { 1559 | "version": "2.0.0", 1560 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1561 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 1562 | "dev": true 1563 | }, 1564 | "setimmediate": { 1565 | "version": "1.0.5", 1566 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 1567 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" 1568 | }, 1569 | "setprototypeof": { 1570 | "version": "1.1.1", 1571 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1572 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", 1573 | "dev": true 1574 | }, 1575 | "sha.js": { 1576 | "version": "2.4.11", 1577 | "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", 1578 | "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", 1579 | "requires": { 1580 | "inherits": "^2.0.1", 1581 | "safe-buffer": "^5.0.1" 1582 | } 1583 | }, 1584 | "shadow-cljs": { 1585 | "version": "2.8.83", 1586 | "resolved": "https://registry.npmjs.org/shadow-cljs/-/shadow-cljs-2.8.83.tgz", 1587 | "integrity": "sha512-oqqSLARvYXopA9QLf5znrguvJOSRm65LYL9XHuRWaUbMGXlygqgCjSFgW1yREXmqUQ+i2TLoA1zulYO6nTTy6g==", 1588 | "requires": { 1589 | "mkdirp": "^0.5.1", 1590 | "node-libs-browser": "^2.0.0", 1591 | "readline-sync": "^1.4.7", 1592 | "shadow-cljs-jar": "1.3.1", 1593 | "source-map-support": "^0.4.15", 1594 | "which": "^1.3.1", 1595 | "ws": "^3.0.0" 1596 | } 1597 | }, 1598 | "shadow-cljs-jar": { 1599 | "version": "1.3.1", 1600 | "resolved": "https://registry.npmjs.org/shadow-cljs-jar/-/shadow-cljs-jar-1.3.1.tgz", 1601 | "integrity": "sha512-IJSm4Gfu/wWDsOQ0wNrSxuaGdjzsd78us+3bop3cpWsoO2Igdu6VIBItYrZHRRBKl5LIZKXfnSh/2eWG3C1EFw==" 1602 | }, 1603 | "socket.io": { 1604 | "version": "2.1.1", 1605 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", 1606 | "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", 1607 | "dev": true, 1608 | "requires": { 1609 | "debug": "~3.1.0", 1610 | "engine.io": "~3.2.0", 1611 | "has-binary2": "~1.0.2", 1612 | "socket.io-adapter": "~1.1.0", 1613 | "socket.io-client": "2.1.1", 1614 | "socket.io-parser": "~3.2.0" 1615 | }, 1616 | "dependencies": { 1617 | "debug": { 1618 | "version": "3.1.0", 1619 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1620 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1621 | "dev": true, 1622 | "requires": { 1623 | "ms": "2.0.0" 1624 | } 1625 | } 1626 | } 1627 | }, 1628 | "socket.io-adapter": { 1629 | "version": "1.1.2", 1630 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", 1631 | "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", 1632 | "dev": true 1633 | }, 1634 | "socket.io-client": { 1635 | "version": "2.1.1", 1636 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", 1637 | "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", 1638 | "dev": true, 1639 | "requires": { 1640 | "backo2": "1.0.2", 1641 | "base64-arraybuffer": "0.1.5", 1642 | "component-bind": "1.0.0", 1643 | "component-emitter": "1.2.1", 1644 | "debug": "~3.1.0", 1645 | "engine.io-client": "~3.2.0", 1646 | "has-binary2": "~1.0.2", 1647 | "has-cors": "1.1.0", 1648 | "indexof": "0.0.1", 1649 | "object-component": "0.0.3", 1650 | "parseqs": "0.0.5", 1651 | "parseuri": "0.0.5", 1652 | "socket.io-parser": "~3.2.0", 1653 | "to-array": "0.1.4" 1654 | }, 1655 | "dependencies": { 1656 | "debug": { 1657 | "version": "3.1.0", 1658 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1659 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1660 | "dev": true, 1661 | "requires": { 1662 | "ms": "2.0.0" 1663 | } 1664 | } 1665 | } 1666 | }, 1667 | "socket.io-parser": { 1668 | "version": "3.2.0", 1669 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", 1670 | "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", 1671 | "dev": true, 1672 | "requires": { 1673 | "component-emitter": "1.2.1", 1674 | "debug": "~3.1.0", 1675 | "isarray": "2.0.1" 1676 | }, 1677 | "dependencies": { 1678 | "debug": { 1679 | "version": "3.1.0", 1680 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1681 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1682 | "dev": true, 1683 | "requires": { 1684 | "ms": "2.0.0" 1685 | } 1686 | }, 1687 | "isarray": { 1688 | "version": "2.0.1", 1689 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 1690 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", 1691 | "dev": true 1692 | } 1693 | } 1694 | }, 1695 | "source-map": { 1696 | "version": "0.5.7", 1697 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1698 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 1699 | }, 1700 | "source-map-support": { 1701 | "version": "0.4.18", 1702 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", 1703 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", 1704 | "requires": { 1705 | "source-map": "^0.5.6" 1706 | } 1707 | }, 1708 | "statuses": { 1709 | "version": "1.5.0", 1710 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1711 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 1712 | "dev": true 1713 | }, 1714 | "stream-browserify": { 1715 | "version": "2.0.2", 1716 | "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", 1717 | "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", 1718 | "requires": { 1719 | "inherits": "~2.0.1", 1720 | "readable-stream": "^2.0.2" 1721 | } 1722 | }, 1723 | "stream-http": { 1724 | "version": "2.8.3", 1725 | "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", 1726 | "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", 1727 | "requires": { 1728 | "builtin-status-codes": "^3.0.0", 1729 | "inherits": "^2.0.1", 1730 | "readable-stream": "^2.3.6", 1731 | "to-arraybuffer": "^1.0.0", 1732 | "xtend": "^4.0.0" 1733 | } 1734 | }, 1735 | "streamroller": { 1736 | "version": "1.0.6", 1737 | "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", 1738 | "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", 1739 | "dev": true, 1740 | "requires": { 1741 | "async": "^2.6.2", 1742 | "date-format": "^2.0.0", 1743 | "debug": "^3.2.6", 1744 | "fs-extra": "^7.0.1", 1745 | "lodash": "^4.17.14" 1746 | }, 1747 | "dependencies": { 1748 | "debug": { 1749 | "version": "3.2.6", 1750 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 1751 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 1752 | "dev": true, 1753 | "requires": { 1754 | "ms": "^2.1.1" 1755 | } 1756 | }, 1757 | "ms": { 1758 | "version": "2.1.2", 1759 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1760 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1761 | "dev": true 1762 | } 1763 | } 1764 | }, 1765 | "string-width": { 1766 | "version": "4.2.0", 1767 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 1768 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 1769 | "dev": true, 1770 | "requires": { 1771 | "emoji-regex": "^8.0.0", 1772 | "is-fullwidth-code-point": "^3.0.0", 1773 | "strip-ansi": "^6.0.0" 1774 | } 1775 | }, 1776 | "string_decoder": { 1777 | "version": "1.3.0", 1778 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1779 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1780 | "requires": { 1781 | "safe-buffer": "~5.2.0" 1782 | } 1783 | }, 1784 | "strip-ansi": { 1785 | "version": "6.0.0", 1786 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 1787 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 1788 | "dev": true, 1789 | "requires": { 1790 | "ansi-regex": "^5.0.0" 1791 | } 1792 | }, 1793 | "timers-browserify": { 1794 | "version": "2.0.11", 1795 | "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", 1796 | "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", 1797 | "requires": { 1798 | "setimmediate": "^1.0.4" 1799 | } 1800 | }, 1801 | "tmp": { 1802 | "version": "0.0.33", 1803 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1804 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1805 | "dev": true, 1806 | "requires": { 1807 | "os-tmpdir": "~1.0.2" 1808 | } 1809 | }, 1810 | "to-array": { 1811 | "version": "0.1.4", 1812 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 1813 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", 1814 | "dev": true 1815 | }, 1816 | "to-arraybuffer": { 1817 | "version": "1.0.1", 1818 | "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", 1819 | "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" 1820 | }, 1821 | "to-regex-range": { 1822 | "version": "5.0.1", 1823 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1824 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1825 | "dev": true, 1826 | "requires": { 1827 | "is-number": "^7.0.0" 1828 | } 1829 | }, 1830 | "toidentifier": { 1831 | "version": "1.0.0", 1832 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1833 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", 1834 | "dev": true 1835 | }, 1836 | "tty-browserify": { 1837 | "version": "0.0.0", 1838 | "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", 1839 | "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" 1840 | }, 1841 | "type-is": { 1842 | "version": "1.6.18", 1843 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1844 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1845 | "dev": true, 1846 | "requires": { 1847 | "media-typer": "0.3.0", 1848 | "mime-types": "~2.1.24" 1849 | } 1850 | }, 1851 | "ua-parser-js": { 1852 | "version": "0.7.21", 1853 | "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", 1854 | "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==", 1855 | "dev": true 1856 | }, 1857 | "ultron": { 1858 | "version": "1.1.1", 1859 | "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", 1860 | "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" 1861 | }, 1862 | "universalify": { 1863 | "version": "0.1.2", 1864 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1865 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 1866 | "dev": true 1867 | }, 1868 | "unpipe": { 1869 | "version": "1.0.0", 1870 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1871 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 1872 | "dev": true 1873 | }, 1874 | "url": { 1875 | "version": "0.11.0", 1876 | "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", 1877 | "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", 1878 | "requires": { 1879 | "punycode": "1.3.2", 1880 | "querystring": "0.2.0" 1881 | }, 1882 | "dependencies": { 1883 | "punycode": { 1884 | "version": "1.3.2", 1885 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 1886 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 1887 | } 1888 | } 1889 | }, 1890 | "util": { 1891 | "version": "0.11.1", 1892 | "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", 1893 | "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", 1894 | "requires": { 1895 | "inherits": "2.0.3" 1896 | }, 1897 | "dependencies": { 1898 | "inherits": { 1899 | "version": "2.0.3", 1900 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1901 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 1902 | } 1903 | } 1904 | }, 1905 | "util-deprecate": { 1906 | "version": "1.0.2", 1907 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1908 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1909 | }, 1910 | "utils-merge": { 1911 | "version": "1.0.1", 1912 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1913 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 1914 | "dev": true 1915 | }, 1916 | "vm-browserify": { 1917 | "version": "1.1.2", 1918 | "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", 1919 | "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" 1920 | }, 1921 | "void-elements": { 1922 | "version": "2.0.1", 1923 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", 1924 | "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", 1925 | "dev": true 1926 | }, 1927 | "which": { 1928 | "version": "1.3.1", 1929 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1930 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1931 | "requires": { 1932 | "isexe": "^2.0.0" 1933 | } 1934 | }, 1935 | "which-module": { 1936 | "version": "2.0.0", 1937 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1938 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 1939 | "dev": true 1940 | }, 1941 | "wrap-ansi": { 1942 | "version": "6.2.0", 1943 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 1944 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 1945 | "dev": true, 1946 | "requires": { 1947 | "ansi-styles": "^4.0.0", 1948 | "string-width": "^4.1.0", 1949 | "strip-ansi": "^6.0.0" 1950 | } 1951 | }, 1952 | "wrappy": { 1953 | "version": "1.0.2", 1954 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1955 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1956 | "dev": true 1957 | }, 1958 | "ws": { 1959 | "version": "3.3.3", 1960 | "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", 1961 | "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", 1962 | "requires": { 1963 | "async-limiter": "~1.0.0", 1964 | "safe-buffer": "~5.1.0", 1965 | "ultron": "~1.1.0" 1966 | }, 1967 | "dependencies": { 1968 | "safe-buffer": { 1969 | "version": "5.1.2", 1970 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1971 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1972 | } 1973 | } 1974 | }, 1975 | "xmlhttprequest-ssl": { 1976 | "version": "1.5.5", 1977 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", 1978 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", 1979 | "dev": true 1980 | }, 1981 | "xtend": { 1982 | "version": "4.0.2", 1983 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1984 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 1985 | }, 1986 | "y18n": { 1987 | "version": "4.0.0", 1988 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 1989 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 1990 | "dev": true 1991 | }, 1992 | "yargs": { 1993 | "version": "15.3.1", 1994 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", 1995 | "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", 1996 | "dev": true, 1997 | "requires": { 1998 | "cliui": "^6.0.0", 1999 | "decamelize": "^1.2.0", 2000 | "find-up": "^4.1.0", 2001 | "get-caller-file": "^2.0.1", 2002 | "require-directory": "^2.1.1", 2003 | "require-main-filename": "^2.0.0", 2004 | "set-blocking": "^2.0.0", 2005 | "string-width": "^4.2.0", 2006 | "which-module": "^2.0.0", 2007 | "y18n": "^4.0.0", 2008 | "yargs-parser": "^18.1.1" 2009 | } 2010 | }, 2011 | "yargs-parser": { 2012 | "version": "18.1.3", 2013 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 2014 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 2015 | "dev": true, 2016 | "requires": { 2017 | "camelcase": "^5.0.0", 2018 | "decamelize": "^1.2.0" 2019 | } 2020 | }, 2021 | "yeast": { 2022 | "version": "0.1.2", 2023 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 2024 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", 2025 | "dev": true 2026 | } 2027 | } 2028 | } 2029 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wsscode-async", 3 | "version": "1.0.0", 4 | "description": "= WSSCode Async Helpers", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "shadow-cljs": "^2.8.83" 16 | }, 17 | "devDependencies": { 18 | "karma": "^5.0.3", 19 | "karma-chrome-launcher": "^3.1.0", 20 | "karma-cljs-test": "^0.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.wsscode 5 | async 6 | jar 7 | 2021.01.14 8 | async 9 | Helpers for Clojure core.async. 10 | https://github.com/wilkerlucio/wsscode-async 11 | 12 | 13 | MIT 14 | https://opensource.org/licenses/MIT 15 | 16 | 17 | 18 | https://github.com/wilkerlucio/wsscode-async 19 | scm:git:git://github.com/wilkerlucio/wsscode-async.git 20 | scm:git:ssh://git@github.com/wilkerlucio/wsscode-async.git 21 | 40cd60df8042c2b9e7881d55f789974abcd59a70 22 | 23 | 24 | src 25 | test 26 | 27 | 28 | resources 29 | 30 | 31 | 32 | 33 | resources 34 | 35 | 36 | target 37 | target/classes 38 | 39 | 40 | 41 | 42 | central 43 | https://repo1.maven.org/maven2/ 44 | 45 | false 46 | 47 | 48 | true 49 | 50 | 51 | 52 | clojars 53 | https://repo.clojars.org/ 54 | 55 | true 56 | 57 | 58 | true 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | org.clojure 68 | core.async 69 | 1.3.610 70 | 71 | 72 | 73 | 74 | 78 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject com.wsscode/async "2021.01.15" 2 | :description "Helpers for Clojure core.async." 3 | :url "https://github.com/wilkerlucio/wsscode-async" 4 | :license {:name "MIT" 5 | :url "https://opensource.org/licenses/MIT"} 6 | 7 | :source-paths ["src"] 8 | 9 | :dependencies [[org.clojure/core.async "1.3.610"]] 10 | 11 | :jar-exclusions [#"node-modules/.+"] 12 | 13 | :deploy-repositories [["clojars" {:url "https://clojars.org/repo/" 14 | :creds :gpg :checksum :ignore}] 15 | ["releases" :clojars] 16 | ["snapshots" :clojars]]) 17 | -------------------------------------------------------------------------------- /resources/clj-kondo.exports/com.wsscode/async/config.edn: -------------------------------------------------------------------------------- 1 | {:lint-as {com.wsscode.async.async-clj/deftest-async clojure.test/deftest 2 | com.wsscode.async.async-clj/go-try-stream clojure.core/let 3 | com.wsscode.async.async-clj/let-chan clojure.core/let 4 | com.wsscode.async.async-clj/let-chan* clojure.core/let 5 | com.wsscode.async.async-cljs/deftest-async clojure.test/deftest 6 | com.wsscode.async.async-cljs/go-try-stream clojure.core/let 7 | com.wsscode.async.async-cljs/let-chan clojure.core/let 8 | com.wsscode.async.async-cljs/let-chan* clojure.core/let}} 9 | -------------------------------------------------------------------------------- /script/release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | lein vcs tag v 4 | git push --follow-tags 5 | lein deploy clojars 6 | -------------------------------------------------------------------------------- /script/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | clojure -A:test 4 | -------------------------------------------------------------------------------- /shadow-cljs.edn: -------------------------------------------------------------------------------- 1 | {:deps {:aliases [:provided :test-cljs]} 2 | :nrepl {:port 9538} 3 | :builds {:test {:target :browser-test 4 | :test-dir "target-cljs/public/js/test" 5 | :ns-regexp "-test$" 6 | :compiler-options {:static-fns false 7 | :external-config {:guardrails {:throw? true :emit-spec? true}}} 8 | :devtools {:http-port 9158 9 | :http-resource-root "public" 10 | :http-root "target-cljs/public/js/test"}} 11 | :ci {:target :karma 12 | :compiler-options {:output-feature-set :es6} 13 | :ns-regexp "-test$" 14 | :output-to "target/ci.js"}}} 15 | -------------------------------------------------------------------------------- /src/com/wsscode/async/async_clj.clj: -------------------------------------------------------------------------------- 1 | (ns com.wsscode.async.async-clj 2 | (:require [clojure.core.async :as async] 3 | [clojure.core.async.impl.protocols :as async.prot] 4 | [clojure.spec.alpha :as s])) 5 | 6 | (defn chan? 7 | "Check if c is a core.async channel." 8 | [c] 9 | (satisfies? async.prot/ReadPort c)) 10 | 11 | (defmacro go 12 | "Same as `clojure.core.async/go`. Just a convenience place for it." 13 | [& body] 14 | `(async/go ~@body)) 15 | 16 | (defmacro go-loop 17 | "Same as `clojure.core.async/go-loop`. Just a convenience place for it." 18 | [bindings & body] 19 | `(async/go-loop ~bindings ~@body)) 20 | 21 | (defmacro thread 22 | "Same as `clojure.core.async/thread`. Just a convenience place for it." 23 | [& body] 24 | `(async/thread ~@body)) 25 | 26 | (defmacro catch-all 27 | "Catches all Throwable exceptions and returns them as-is." 28 | [& body] 29 | `(try 30 | ~@body 31 | (catch Throwable e# e#))) 32 | 33 | (defmacro go-catch 34 | "Creates a go block that has a try/catch wrapping body, in case of errors the error 35 | flows up as data instead triggering the exception." 36 | [& body] 37 | `(async/go (catch-all ~@body))) 38 | 39 | (defmacro thread-catch 40 | "Creates a thread that has a try/catch wrapping body, in case of errors the error 41 | flows up as data instead triggering the exception." 42 | [& body] 43 | `(async/thread (catch-all ~@body))) 44 | 45 | (defmacro nil-safe-put! 46 | "Puts result of body on the provided channel if non-nil, else it closes it. 47 | A workaround to allow communicating nils." 48 | [ch & body] 49 | `(if-some [res# (catch-all ~@body)] 50 | (async/put! ~ch res#) 51 | (async/close! ~ch))) 52 | 53 | (defmacro go-promise 54 | "Creates a go block using a promise channel, so the output of the go block can be 55 | read any number of times once ready." 56 | [& body] 57 | `(let [ch# (async/promise-chan)] 58 | (async/go (nil-safe-put! ch# ~@body)) 59 | ch#)) 60 | 61 | (defmacro thread-promise 62 | "Creates a thread using a promise channel, so the output of the thread block can be 63 | read any number of times once ready." 64 | [& body] 65 | `(let [ch# (async/promise-chan)] 66 | (async/thread (nil-safe-put! ch# ~@body)) 67 | ch#)) 68 | 69 | (defn error? 70 | "Returns true if err is an error object." 71 | [err] 72 | (instance? Throwable err)) 73 | 74 | (defn throw-err 75 | "Throw error x if x is an error." 76 | [x] 77 | (if (error? x) 78 | (throw x) 79 | x)) 80 | 81 | (defmacro (js/fetch \"some-url\") chan ~promise)))) 55 | 56 | (defmacro chan 20 | "Converts promise p in a promise-chan. The response of this channel should be consumed 21 | using `consume-pair`." 22 | [p] 23 | (let [c (async/promise-chan)] 24 | (.then p 25 | #(async/put! c {:success %}) 26 | #(async/put! c {:error %})) 27 | c)) 28 | 29 | (defn consumer-pair 30 | "Consume promise channel result pair." 31 | [resp] 32 | (if (contains? resp :error) 33 | (throw (:error resp)) 34 | (:success resp))) 35 | 36 | (defn error? 37 | "Returns true if err is an error object." 38 | [err] 39 | (instance? js/Error err)) 40 | 41 | (defn throw-err 42 | "Throw error x if x is an error." 43 | [x] 44 | (if (error? x) 45 | (throw x) 46 | x)) 47 | 48 | (defn timeout-chan 49 | "Returns a channel that will respond will c, or an error after timeout-ms." 50 | [timeout-ms c] 51 | (go-promise 52 | (let [timer (async/timeout timeout-ms) 53 | [res ch] (async/alts! [c timer] :priority true)] 54 | (if (= ch timer) 55 | (throw (ex-info "Timeout" {:timeout-ms timeout-ms})) 56 | res)))) 57 | 58 | (defn pulling-retry* 59 | [options f] 60 | (let [options' (if (map? options) 61 | options 62 | {::done? options}) 63 | {::keys [done? timeout retry-ms] 64 | :or {retry-ms 10 65 | timeout 2000}} options' 66 | *stop? (atom false) 67 | res (timeout-chan timeout 68 | (go-promise 69 | (loop [] 70 | (when-not @*stop? 71 | (let [res ( (? ::channel)] 33 | (if (and request-id (not request-response)) 34 | (let [chan (async/promise-chan) 35 | timeout' (or timeout *default-timeout*) 36 | timer (async/timeout timeout')] 37 | (swap! response-notifiers* assoc request-id chan) 38 | (go-promise 39 | (let [[val ch] (async/alts! [chan timer] :priority true)] 40 | (swap! response-notifiers* dissoc request-id) 41 | (if (= ch timer) 42 | (ex-info "Response timeout" {:timeout timeout' 43 | ::request-id request-id 44 | :request-keys (keys msg)}) 45 | val)))))) 46 | 47 | (defn capture-response! 48 | "Use this helper in the receiving side of events, right before sending to your original 49 | handler message. This will ensure that response messages are propagated back to the 50 | listener." 51 | [{::keys [response-id request-response]}] 52 | #_[(? (s/keys :opt [::response-id ::request-response])) 53 | => (s/or :captured true? :ignored nil?)] 54 | (when request-response 55 | (if-let [chan (get @response-notifiers* response-id)] 56 | (async/put! chan request-response) 57 | (print "Tried to notify unavailable responder" response-id)) 58 | true)) 59 | 60 | (defn reply-message 61 | "Helper to make a response map for a given message with a request-id. 62 | 63 | Use this to generate response data from async events." 64 | [{::keys [request-id]} value] 65 | #_[(s/keys :req [::request-id]) any? 66 | => (s/keys :req [::response-id ::request-response])] 67 | {::response-id request-id 68 | ::request-response value}) 69 | 70 | (defn event-queue! 71 | "Returns a callback handler that will respond to events in a serialized queue. When 72 | the user handler returns a channel, the next message will wait until the current one 73 | finished processing before moving on. Use this on callback handlers that need serialization 74 | to avoid concurrency issues." 75 | ([handler] #_[fn? => any?] 76 | (event-queue! {} handler)) 77 | ([{::keys [channel]} handler] 78 | #_[(s/keys :opt [::channel]) fn? 79 | => any?] 80 | (let [channel' (or channel (chan (async/dropping-buffer 1024)))] 81 | (go-loop [] 82 | (when-let [args (