diff --git a/.gitignore b/.gitignore index d8be4e4..46fdef9 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ repl-public repl-node test .env +app +nodejs.js diff --git a/build.boot b/build.boot index a74192f..0171b22 100644 --- a/build.boot +++ b/build.boot @@ -9,7 +9,8 @@ :resource-paths #{"src"}) (require - '[degree9.boot-semver :refer :all]) + '[degree9.boot-semver :refer :all] + '[meta.boot :as m]) (task-options! pom {:project 'degree9/enterprise @@ -33,3 +34,21 @@ :pre-release 'snapshot) (watch) (build-jar))) + +(m/initialize) + +(deftask build + "Start production build." + [] + (comp + (m/info) + (m/standup) + (m/client :develop true) + (m/server :develop true) + (m/teardown) + (m/package))) + +(deftask m-develop + "Start local development." + [] + (m/develop)) diff --git a/default.nix b/default.nix index 39623dd..51baf0d 100644 --- a/default.nix +++ b/default.nix @@ -14,6 +14,8 @@ with nix-shell.pkgs; SUPPRESS_NO_CONFIG_WARNING = "true"; ENV_TEST_VAR = "foo"; + APP_PORT = "5678"; + DEBUG = "degree9:*"; shellHook = nix-shell.pkgs.lib.concatStrings [ # extra shellHook commands here @@ -24,6 +26,9 @@ with nix-shell.pkgs; buildInputs = [ + nix-shell.pkgs.ngrok + nix-shell.pkgs.boot + (nix-shell.pkgs.writeShellScriptBin "flush" '' rm -rf ./node_modules @@ -52,6 +57,11 @@ with nix-shell.pkgs; node-test browser-test '') + + (nix-shell.pkgs.writeShellScriptBin "expose-local" + '' + ngrok http $APP_PORT + '') ] ++ nix-shell.shell.buildInputs ; diff --git a/package-lock.json b/package-lock.json index 6da38fb..c2e655a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -257,6 +257,11 @@ "picomatch": "^2.0.4" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "applicationinsights": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.4.2.tgz", @@ -633,8 +638,7 @@ "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "buffer-xor": { "version": "1.0.3", @@ -648,6 +652,38 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -768,6 +804,17 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "config": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/config/-/config-3.2.2.tgz", @@ -1067,6 +1114,38 @@ "resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.3.3.tgz", "integrity": "sha512-qIocRYU5TrGUkBlDDxaziAK1+squ8Yf2Ls4HldL3xxb/jzmWO2Enux7CvevNKYmF2kDXZ9HiRqwjPsjk8L+i2Q==" }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -2453,7 +2532,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -2461,8 +2539,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } }, @@ -2554,6 +2631,21 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "multer": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", + "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -3514,6 +3606,11 @@ } } }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -3685,6 +3782,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "uberproto": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/uberproto/-/uberproto-2.0.4.tgz", @@ -3893,8 +3995,7 @@ "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "yallist": { "version": "2.1.2", diff --git a/package.json b/package.json index 783f19e..b2f7ea2 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "hellosign-sdk": "^1.3.1", "jquery": "^3.4.1", "mongoose": "^5.7.1", + "multer": "^1.4.2", "node-fetch": "^2.6.0", "request": "^2.88.0", "request-compose": "=1.2.0", diff --git a/shadow-cljs.edn b/shadow-cljs.edn index 656f200..770d839 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -19,6 +19,8 @@ [funcool/cuerdas "2.1.0"] [degree9/meta "0.5.0-SNAPSHOT"] [degree9/uikit-hl "3.0.0-SNAPSHOT"] + [degree9/boot-shadow "2.8.14-0"] + [thheller/shadow-cljs "2.8.31"] ; testing [degree9/boot-semver "1.8.0" :scope "test"] @@ -39,8 +41,8 @@ :asset-path "/js" :compiler-options {:reader-features #{:node}} - :closure-defines - {degree9.twilio.fax.fixture/-test-fax-number #shadow/env "TWILIO_TEST_FAX_NUMBER"} + ; :closure-defines + ; {degree9.twilio.fax.fixture/-test-fax-number #shadow/env "TWILIO_TEST_FAX_NUMBER"} :modules {:main @@ -50,6 +52,18 @@ {:http-root "repl-public" :http-port 8020}} + :server + { + :target :node-script + :main degree9.server/start! + :output-dir "app" + :output-to "nodejs.js" + :compiler-options + {:reader-features #{:node} + :optimizations :simple}} + ; :closure-defines + ; {degree9.twilio.fax.fixtures/-test-fax-number #shadow/env "TWILIO_TEST_FAX_NUMBER"}} + :node-test { :target :node-test @@ -63,6 +77,6 @@ :target :karma :output-to "test/browser.js" :compiler-options - {:reader-features #{:browser}} - :closure-defines - {degree9.twilio.fax.fixture/-test-fax-number #shadow/env "TWILIO_TEST_FAX_NUMBER"}}}} + {:reader-features #{:browser}}}}} + ; :closure-defines + ; {degree9.twilio.fax.fixture/-test-fax-number #shadow/env "TWILIO_TEST_FAX_NUMBER"}}}} diff --git a/src/degree9/hellosign/callback.cljs b/src/degree9/hellosign/callback.cljs new file mode 100644 index 0000000..0e62193 --- /dev/null +++ b/src/degree9/hellosign/callback.cljs @@ -0,0 +1,49 @@ +(ns degree9.hellosign.callback + (:require + degree9.multipart-form + degree9.twilio.fax.fixture + degree9.twilio.fax.api + degree9.twilio.client + degree9.hellosign.core)) + +(defn all-signed! []) + +(defn data->parsed [data] + (js->clj + (.parse js/JSON + (.-json data)) + :keywordize-keys true)) + +(defn parsed->final-copy-url [parsed] + (str + "https://" + (degree9.hellosign.core/api-key) + ":@api.hellosign.com" + (:final_copy_uri (:signature_request parsed)))) + +(defn hellosign-success + [resolve reject] + (resolve "Hello API Event Received")) + +(defn hellosign-service [& opts] + (reify Object + (create [this data params] + (let [parsed (data->parsed data)] + (when + (and + (-> parsed :event :event_type #{"signature_request_all_signed"}) + (-> parsed :signature_request :has_error not) + (-> parsed :signature_request :is_complete) + (-> parsed :signature_request :is_declined not)) + (.then + (degree9.twilio.fax.api/fax! + (degree9.twilio.client/client!) + (degree9.twilio.fax.fixture/simple-fax-request (parsed->final-copy-url parsed))) + hellosign-success)) + (js/Promise. hellosign-success))))) + +(defn with-callback! [app] + (degree9.multipart-form/multipart-none + app + "/hellosign/callback" + (hellosign-service))) diff --git a/src/degree9/hellosign/core.cljs b/src/degree9/hellosign/core.cljs index 9249388..adddb29 100644 --- a/src/degree9/hellosign/core.cljs +++ b/src/degree9/hellosign/core.cljs @@ -3,7 +3,10 @@ [degree9.env :as env] ["hellosign-sdk" :as hello])) -(def hellosign (hello #js{:key (env/get "HELLOSIGN_API_KEY")})) +(defn api-key [] + #js{:key (env/get "HELLOSIGN_API_KEY")}) + +(def hellosign (hello (api-key))) (def template (obj/get hellosign "template")) diff --git a/src/degree9/server.cljs b/src/degree9/server.cljs index c573ea5..6f36af5 100644 --- a/src/degree9/server.cljs +++ b/src/degree9/server.cljs @@ -3,7 +3,8 @@ ["debug" :as dbg] [meta.server :as server] [degree9.env :as env] - [degree9.channels :as chan])) + [degree9.channels :as chan] + degree9.hellosign.callback)) (def ^:private debug (dbg "degree9:enterprise:server")) @@ -18,7 +19,19 @@ (:channels opts) (chan/with-channels) (:auth opts) (server/with-authentication)))) -(defn start! [app] +(defn start! + ([] + (start! + (-> + (app + :default + :rest + :socket + :channels) + degree9.hellosign.callback/with-callback!))) + ; :auth + + ([app] (let [port (env/get "APP_PORT")] (debug "Server listening on port %s" port) - (server/listen app port))) + (server/listen app port)))) diff --git a/src/degree9/twilio/fax/fixture.cljc b/src/degree9/twilio/fax/fixture.cljc index 0037869..b497045 100644 --- a/src/degree9/twilio/fax/fixture.cljc +++ b/src/degree9/twilio/fax/fixture.cljc @@ -10,11 +10,19 @@ ; this needs to be a fax number that is fax enabled in twilio dashboard #?(:node - (def -test-fax-number - (degree9.env/get :twilio-test-fax-number)) + (def -test-fax-number-to + (degree9.env/get :twilio-test-fax-number-to)) :browser - (goog-define -test-fax-number "")) -(defn test-fax-number [] -test-fax-number) + (goog-define -test-fax-number-to "")) +(defn test-fax-number-to [] -test-fax-number-to) + +; this needs to be a fax number that is fax enabled in twilio dashboard +#?(:node + (def -test-fax-number-from + (degree9.env/get :twilio-test-fax-number-from)) + :browser + (goog-define -test-fax-number-from "")) +(defn test-fax-number-from [] -test-fax-number-from) ; sends ; the example pdf url @@ -23,8 +31,8 @@ (defn simple-fax-request ([] (simple-fax-request (example-pdf-url))) ([media-url] - {:from (test-fax-number) - :to (test-fax-number) + {:from (test-fax-number-from) + :to (test-fax-number-to) :mediaUrl media-url})) (defn example-fax-instance