diff --git a/.gitignore b/.gitignore index 9982c50..97ac482 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.stack-work/ +*~ elm-stuff repl-temp-* dist diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a361c68 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +build: client-build server-build + +client-build: + (cd client ; make) + +server-build: + stack build + +install: + stack install diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..a0543ab --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: chordsheetify-exe diff --git a/README.md b/README.md index 342ffcb..84b93cc 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -[![Netlify Status](https://api.netlify.com/api/v1/badges/396fdb4f-dd5e-4ce4-b24f-5afe07d2cd60/deploy-status)](https://app.netlify.com/sites/gracious-poitras-4d06d1/deploys) +# chordsheetify diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/chordsheetify.cabal b/chordsheetify.cabal new file mode 100644 index 0000000..e6627e0 --- /dev/null +++ b/chordsheetify.cabal @@ -0,0 +1,75 @@ +cabal-version: 1.12 + +-- This file has been generated from package.yaml by hpack version 0.33.0. +-- +-- see: https://github.com/sol/hpack +-- +-- hash: 0970cea64d239429c35b719155e4cf97e2fa8ed26542ff065ac48c7baf3b9248 + +name: chordsheetify +version: 0.1.0.0 +description: Please see the README on GitHub at +homepage: https://github.com/zcesur/chordsheetify#readme +bug-reports: https://github.com/zcesur/chordsheetify/issues +author: Zafer Cesur +maintainer: 17045339+zcesur@users.noreply.github.com +copyright: 2020 Zafer Cesur +build-type: Simple +extra-source-files: + README.md + +source-repository head + type: git + location: https://github.com/zcesur/chordsheetify + +executable chordsheetify-exe + main-is: Main.hs + other-modules: + Api + App + Paths_chordsheetify + hs-source-dirs: + server + ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N + build-depends: + base >=4.7 && <5 + , bytestring + , elm-bridge + , lens + , postgresql-simple + , resource-pool + , servant-elm + , servant-server + , servant-swagger + , servant-swagger-ui + , swagger2 + , wai + , wai-app-static + , warp + default-language: Haskell2010 + +test-suite chordsheetify-test + type: exitcode-stdio-1.0 + main-is: Spec.hs + other-modules: + Paths_chordsheetify + hs-source-dirs: + test + ghc-options: -threaded -rtsopts -with-rtsopts=-N + build-depends: + base >=4.7 && <5 + , bytestring + , chordsheetify + , elm-bridge + , lens + , postgresql-simple + , resource-pool + , servant-elm + , servant-server + , servant-swagger + , servant-swagger-ui + , swagger2 + , wai + , wai-app-static + , warp + default-language: Haskell2010 diff --git a/client/GenerateElm.hs b/client/GenerateElm.hs new file mode 100644 index 0000000..93ab290 --- /dev/null +++ b/client/GenerateElm.hs @@ -0,0 +1,19 @@ +{-# LANGUAGE OverloadedStrings #-} + +import Servant.Elm ( DefineElm(DefineElm) + , Proxy(Proxy) + , UrlPrefix(Static) + , defElmImports + , defElmOptions + , generateElmModuleWith + ) +import Api + +main :: IO () +main = generateElmModuleWith + defElmOptions + ["Api"] + defElmImports + "client/src" + [DefineElm (Proxy :: Proxy Sheet), DefineElm (Proxy :: Proxy SheetId)] + (Proxy :: Proxy RestApi) diff --git a/client/Makefile b/client/Makefile new file mode 100644 index 0000000..91affeb --- /dev/null +++ b/client/Makefile @@ -0,0 +1,9 @@ +all: src/Api.elm build + +src/Api.elm: GenerateElm.hs ../server/Api.hs + (cd ../ ; stack exec -- runhaskell -iserver client/GenerateElm.hs) + +.PHONY: build +build: + yarn install + yarn build diff --git a/assets/logo.svg b/client/assets/logo.svg similarity index 100% rename from assets/logo.svg rename to client/assets/logo.svg diff --git a/elm.json b/client/elm.json similarity index 100% rename from elm.json rename to client/elm.json diff --git a/index.html b/client/index.html similarity index 100% rename from index.html rename to client/index.html diff --git a/index.js b/client/index.js similarity index 100% rename from index.js rename to client/index.js diff --git a/package.json b/client/package.json similarity index 94% rename from package.json rename to client/package.json index 27a12a7..ea88275 100644 --- a/package.json +++ b/client/package.json @@ -4,7 +4,6 @@ "version": "0.1.0", "main": "index.js", "scripts": { - "start": "http-server dist", "build": "webpack" }, "repository": { @@ -24,7 +23,6 @@ "elm": "^0.19.1-3", "elm-webpack-loader": "^6.0.1", "html-webpack-plugin": "^4.3.0", - "http-server": "^0.12.3", "mini-css-extract-plugin": "^0.9.0", "node-sass": "^4.14.1", "optimize-css-assets-webpack-plugin": "^5.0.3", diff --git a/postcss.config.js b/client/postcss.config.js similarity index 100% rename from postcss.config.js rename to client/postcss.config.js diff --git a/public/android-chrome-192x192.png b/client/public/android-chrome-192x192.png similarity index 100% rename from public/android-chrome-192x192.png rename to client/public/android-chrome-192x192.png diff --git a/public/android-chrome-512x512.png b/client/public/android-chrome-512x512.png similarity index 100% rename from public/android-chrome-512x512.png rename to client/public/android-chrome-512x512.png diff --git a/public/apple-touch-icon.png b/client/public/apple-touch-icon.png similarity index 100% rename from public/apple-touch-icon.png rename to client/public/apple-touch-icon.png diff --git a/public/browserconfig.xml b/client/public/browserconfig.xml similarity index 100% rename from public/browserconfig.xml rename to client/public/browserconfig.xml diff --git a/public/favicon-16x16.png b/client/public/favicon-16x16.png similarity index 100% rename from public/favicon-16x16.png rename to client/public/favicon-16x16.png diff --git a/public/favicon-32x32.png b/client/public/favicon-32x32.png similarity index 100% rename from public/favicon-32x32.png rename to client/public/favicon-32x32.png diff --git a/public/favicon.ico b/client/public/favicon.ico similarity index 100% rename from public/favicon.ico rename to client/public/favicon.ico diff --git a/public/manifest.json b/client/public/manifest.json similarity index 100% rename from public/manifest.json rename to client/public/manifest.json diff --git a/public/mstile-144x144.png b/client/public/mstile-144x144.png similarity index 100% rename from public/mstile-144x144.png rename to client/public/mstile-144x144.png diff --git a/public/mstile-150x150.png b/client/public/mstile-150x150.png similarity index 100% rename from public/mstile-150x150.png rename to client/public/mstile-150x150.png diff --git a/public/mstile-310x150.png b/client/public/mstile-310x150.png similarity index 100% rename from public/mstile-310x150.png rename to client/public/mstile-310x150.png diff --git a/public/mstile-310x310.png b/client/public/mstile-310x310.png similarity index 100% rename from public/mstile-310x310.png rename to client/public/mstile-310x310.png diff --git a/public/mstile-70x70.png b/client/public/mstile-70x70.png similarity index 100% rename from public/mstile-70x70.png rename to client/public/mstile-70x70.png diff --git a/public/safari-pinned-tab.svg b/client/public/safari-pinned-tab.svg similarity index 100% rename from public/safari-pinned-tab.svg rename to client/public/safari-pinned-tab.svg diff --git a/src/Api.elm b/client/src/Api.elm similarity index 94% rename from src/Api.elm rename to client/src/Api.elm index 2f0a1fc..bd2fe6d 100644 --- a/src/Api.elm +++ b/client/src/Api.elm @@ -57,7 +57,7 @@ getApiSheets toMsg = , headers = [] , url = - Url.Builder.crossOrigin "https://chordsheetify.herokuapp.com" + Url.Builder.crossOrigin "" [ "api" , "sheets" ] @@ -86,7 +86,7 @@ getApiSheetsById capture_id toMsg = , headers = [] , url = - Url.Builder.crossOrigin "https://chordsheetify.herokuapp.com" + Url.Builder.crossOrigin "" [ "api" , "sheets" , (capture_id |> String.fromInt) diff --git a/src/Chart.elm b/client/src/Chart.elm similarity index 100% rename from src/Chart.elm rename to client/src/Chart.elm diff --git a/src/Instrument.elm b/client/src/Instrument.elm similarity index 100% rename from src/Instrument.elm rename to client/src/Instrument.elm diff --git a/src/Main.elm b/client/src/Main.elm similarity index 100% rename from src/Main.elm rename to client/src/Main.elm diff --git a/src/Ports.elm b/client/src/Ports.elm similarity index 100% rename from src/Ports.elm rename to client/src/Ports.elm diff --git a/src/Shift.elm b/client/src/Shift.elm similarity index 100% rename from src/Shift.elm rename to client/src/Shift.elm diff --git a/src/styles/index.scss b/client/src/styles/index.scss similarity index 100% rename from src/styles/index.scss rename to client/src/styles/index.scss diff --git a/webpack.config.js b/client/webpack.config.js similarity index 100% rename from webpack.config.js rename to client/webpack.config.js diff --git a/yarn.lock b/client/yarn.lock similarity index 98% rename from yarn.lock rename to client/yarn.lock index be24d04..3c8b018 100644 --- a/yarn.lock +++ b/client/yarn.lock @@ -1042,12 +1042,6 @@ async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" -async@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - dependencies: - lodash "^4.17.14" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1112,10 +1106,6 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -basic-auth@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.1.0.tgz#45221ee429f7ee1e5035be3f51533f1cdfd29884" - bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -1561,10 +1551,6 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" -colors@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1660,10 +1646,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -corser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87" - cosmiconfig@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" @@ -1901,12 +1883,6 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.1.1: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - dependencies: - ms "^2.1.1" - debug@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -2065,15 +2041,6 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecstatic@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.3.2.tgz#6d1dd49814d00594682c652adb66076a69d46c48" - dependencies: - he "^1.1.1" - mime "^1.6.0" - minimist "^1.1.0" - url-join "^2.0.5" - electron-to-chromium@^1.3.413: version "1.3.451" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.451.tgz#0c075af3e2f06d706670bde0279432802ca8c83f" @@ -2212,10 +2179,6 @@ esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" -eventemitter3@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - events@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" @@ -2412,12 +2375,6 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@^1.0.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.11.0.tgz#afa14f08ba12a52963140fe43212658897bc0ecb" - dependencies: - debug "^3.0.0" - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2715,7 +2672,7 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -he@^1.1.1, he@^1.2.0: +he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -2790,29 +2747,6 @@ htmlparser2@^3.3.0: inherits "^2.0.1" readable-stream "^3.1.1" -http-proxy@^1.18.0: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -http-server@^0.12.3: - version "0.12.3" - resolved "https://registry.yarnpkg.com/http-server/-/http-server-0.12.3.tgz#ba0471d0ecc425886616cb35c4faf279140a0d37" - dependencies: - basic-auth "^1.0.3" - colors "^1.4.0" - corser "^2.0.1" - ecstatic "^3.3.2" - http-proxy "^1.18.0" - minimist "^1.2.5" - opener "^1.5.1" - portfinder "^1.0.25" - secure-compare "3.0.1" - union "~0.5.0" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -3357,7 +3291,7 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@4.17.15, lodash@^4.0.0, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5, lodash@~4.17.12: +lodash@4.17.15, lodash@^4.0.0, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.5, lodash@~4.17.12: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" @@ -3535,10 +3469,6 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.44.0" -mime@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - mimic-fn@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -3566,7 +3496,7 @@ minimatch@^3.0.4, minimatch@~3.0.2: dependencies: brace-expansion "^1.1.7" -minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -3919,10 +3849,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -opener@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" - optimize-css-assets-webpack-plugin@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz#e2f1d4d94ad8c0af8967ebd7cf138dcb1ef14572" @@ -4185,14 +4111,6 @@ pkg-up@^2.0.0: dependencies: find-up "^2.1.0" -portfinder@^1.0.25: - version "1.0.26" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70" - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.1" - posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -4582,10 +4500,6 @@ q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" -qs@^6.4.0: - version "6.9.4" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" - qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -4792,10 +4706,6 @@ require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -4937,10 +4847,6 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" -secure-compare@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/secure-compare/-/secure-compare-3.0.1.tgz#f1a0329b308b221fae37b9974f3d578d0ca999e3" - "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -5530,12 +5436,6 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -union@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/union/-/union-0.5.0.tgz#b2c11be84f60538537b846edb9ba266ba0090075" - dependencies: - qs "^6.4.0" - uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" @@ -5581,10 +5481,6 @@ urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" -url-join@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728" - url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" diff --git a/package.yaml b/package.yaml new file mode 100644 index 0000000..b8c87a1 --- /dev/null +++ b/package.yaml @@ -0,0 +1,60 @@ +name: chordsheetify +version: 0.1.0.0 +github: "zcesur/chordsheetify" +author: "Zafer Cesur" +maintainer: "17045339+zcesur@users.noreply.github.com" +copyright: "2020 Zafer Cesur" + +extra-source-files: +- README.md + +# Metadata used when publishing your package +# synopsis: Short description of your package +# category: Web + +# To avoid duplicated efforts in documentation and dealing with the +# complications of embedding Haddock markup inside cabal files, it is +# common to point users to the README.md file. +description: Please see the README on GitHub at + +dependencies: +- base >= 4.7 && < 5 +- bytestring +- elm-bridge +- lens +- postgresql-simple +- resource-pool +- servant-elm +- servant-server +- servant-swagger +- servant-swagger-ui +- swagger2 +- wai +- wai-app-static +- warp + +executables: + chordsheetify-exe: + main: Main.hs + source-dirs: + - server + ghc-options: + - -Wall + - -Wcompat + - -Wincomplete-record-updates + - -Wincomplete-uni-patterns + - -Wredundant-constraints + - -threaded + - -rtsopts + - -with-rtsopts=-N + +tests: + chordsheetify-test: + main: Spec.hs + source-dirs: test + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + dependencies: + - chordsheetify diff --git a/server/Api.hs b/server/Api.hs new file mode 100644 index 0000000..d3b34ed --- /dev/null +++ b/server/Api.hs @@ -0,0 +1,44 @@ +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE TypeOperators #-} + +module Api where + +import Data.Swagger +import Database.PostgreSQL.Simple ( FromRow ) +import Database.PostgreSQL.Simple.FromField + ( FromField(..) ) +import GHC.Generics +import Servant +import Servant.Swagger.UI +import qualified Elm.Derive + +type Api = SwaggerSchemaUI "swagger-ui" "swagger.json" :<|> RestApi :<|> Raw +type RestApi = "api" :> SheetApi + +-- brittany-disable-next-binding +type SheetApi = + "sheets" :> Get '[JSON] [Sheet] :<|> + "sheets" :> Capture "id" Int :> Get '[JSON] Sheet + +api :: Proxy Api +api = Proxy + +restApi :: Proxy RestApi +restApi = Proxy + +newtype SheetId = SheetId Int deriving (Show, Generic) +instance FromField SheetId where + fromField field mbs = SheetId <$> fromField field mbs + +data Sheet = Sheet { id :: SheetId, name :: String, content :: String } deriving (Show, Generic, FromRow) + +Elm.Derive.deriveBoth Elm.Derive.defaultOptions ''Sheet +Elm.Derive.deriveBoth Elm.Derive.defaultOptions ''SheetId + +instance ToParamSchema SheetId +instance ToSchema SheetId +instance ToSchema Sheet diff --git a/server/App.hs b/server/App.hs new file mode 100644 index 0000000..ebdb9e0 --- /dev/null +++ b/server/App.hs @@ -0,0 +1,53 @@ +{-# LANGUAGE OverloadedStrings #-} + +module App where + +import Control.Lens +import Control.Monad.IO.Class +import Data.Pool +import Data.Swagger +import Database.PostgreSQL.Simple +import Network.Wai +import Network.Wai.Application.Static +import Servant +import Servant.Swagger +import Servant.Swagger.UI +import WaiAppStatic.Types + +import Api + +mkApp :: Pool Connection -> IO Application +mkApp conns = return $ serve api $ server conns + +server :: Pool Connection -> Server Api +server conns = + swaggerSchemaUIServer apiSwagger + :<|> sheetServer conns + :<|> serveDirectoryWith ss + where + ss = ds { ssLookupFile = lookupFile } + ds = defaultFileServerSettings "client/dist" + lookupFile ps = ssLookupFile ds $ case ps of + [] -> [unsafeToPiece "index.html"] + _ -> ps + +sheetServer :: Pool Connection -> Server SheetApi +sheetServer conns = getSheets :<|> getSheetById + where + getSheets :: Handler [Sheet] + getSheets = + liftIO $ withResource conns $ \conn -> query_ conn "SELECT * FROM sheets" + + getSheetById :: Int -> Handler Sheet + getSheetById sheetId = do + sheets <- liftIO $ withResource conns $ \conn -> + query conn "SELECT * FROM sheets WHERE id = ?" [sheetId] + case sheets of + (s : _) -> return s + [] -> throwError err404 + +-- brittany-disable-next-binding +apiSwagger :: Swagger +apiSwagger = toSwagger restApi + & info.title .~ "Chordsheetify API" + & info.version .~ "1.0.0" diff --git a/server/Main.hs b/server/Main.hs new file mode 100644 index 0000000..5fd88e2 --- /dev/null +++ b/server/Main.hs @@ -0,0 +1,37 @@ +module Main where + +import Data.ByteString ( ByteString ) +import Data.Maybe ( fromMaybe ) +import Data.Pool +import Database.PostgreSQL.Simple +import Network.Wai.Handler.Warp +import System.Environment ( lookupEnv ) +import System.IO +import Text.Read ( readMaybe ) +import qualified Data.ByteString.Char8 as B + +import App + +type DBConnectionString = ByteString + +main :: IO () +main = do + dbEnv <- lookupEnv "DATABASE_URL" + portEnv <- lookupEnv "PORT" + let connStr = fromMaybe defaultConnStr dbEnv + port = fromMaybe defaultPort (portEnv >>= readMaybe) + settings = setPort port $ setBeforeMainLoop + (hPutStrLn stderr ("listening on port " ++ show port)) + defaultSettings + pool <- initConnectionPool (B.pack connStr) + runSettings settings =<< mkApp pool + +initConnectionPool :: DBConnectionString -> IO (Pool Connection) +initConnectionPool connStr = + createPool (connectPostgreSQL connStr) close 2 60 10 + +defaultPort :: Port +defaultPort = 3000 + +defaultConnStr :: String +defaultConnStr = "postgresql://chordsheetify:chordsheetify@localhost" diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..81e4606 --- /dev/null +++ b/stack.yaml @@ -0,0 +1,66 @@ +# This file was automatically generated by 'stack init' +# +# Some commonly used options have been documented as comments in this file. +# For advanced use and comprehensive documentation of the format, please see: +# https://docs.haskellstack.org/en/stable/yaml_configuration/ + +# Resolver to choose a 'specific' stackage snapshot or a compiler version. +# A snapshot resolver dictates the compiler version and the set of packages +# to be used for project dependencies. For example: +# +# resolver: lts-3.5 +# resolver: nightly-2015-09-21 +# resolver: ghc-7.10.2 +# +# The location of a snapshot can be provided as a file or url. Stack assumes +# a snapshot provided as a file might change, whereas a url resource does not. +# +# resolver: ./custom-snapshot.yaml +# resolver: https://example.com/snapshots/2018-01-01.yaml +resolver: lts-16.8 + +# User packages to be built. +# Various formats can be used as shown in the example below. +# +# packages: +# - some-directory +# - https://example.com/foo/bar/baz-0.0.2.tar.gz +# subdirs: +# - auto-update +# - wai +packages: +- . +# Dependency packages to be pulled from upstream that are not in the resolver. +# These entries can reference officially published versions as well as +# forks / in-progress versions pinned to a git hash. For example: +# +# extra-deps: +# - acme-missiles-0.3 +# - git: https://github.com/commercialhaskell/stack.git +# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# +# extra-deps: [] + +# Override default flag values for local packages and extra-deps +# flags: {} + +# Extra package databases containing global packages +# extra-package-dbs: [] + +# Control whether we use the GHC we find on the path +# system-ghc: true +# +# Require a specific version of stack, using version ranges +# require-stack-version: -any # Default +# require-stack-version: ">=2.3" +# +# Override the architecture used by stack, especially useful on Windows +# arch: i386 +# arch: x86_64 +# +# Extra directories used by stack for building +# extra-include-dirs: [/path/to/dir] +# extra-lib-dirs: [/path/to/dir] +# +# Allow a newer minor version of GHC than the snapshot specifies +# compiler-check: newer-minor diff --git a/stack.yaml.lock b/stack.yaml.lock new file mode 100644 index 0000000..7453220 --- /dev/null +++ b/stack.yaml.lock @@ -0,0 +1,12 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: [] +snapshots: +- completed: + size: 532379 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/16/8.yaml + sha256: 2ad3210d2ad35f3176005d68369a18e4d984517bfaa2caade76f28ed0b2e0521 + original: lts-16.8 diff --git a/test/Spec.hs b/test/Spec.hs new file mode 100644 index 0000000..cd4753f --- /dev/null +++ b/test/Spec.hs @@ -0,0 +1,2 @@ +main :: IO () +main = putStrLn "Test suite not yet implemented"