hairy 0.1.1 → 0.1.2
raw patch · 4 files changed
+130/−13 lines, 4 filesdep ~aesondep ~criteriondep ~transformersPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aeson, criterion, transformers
API changes (from Hackage documentation)
Files
- CHANGELOG.md +11/−0
- README.md +84/−4
- hairy.cabal +7/−7
- library/Hairy.lhs +28/−2
CHANGELOG.md view
@@ -1,5 +1,16 @@ # Changelog +# v0.1.2 (2014-10-11)++- Support GHC 7.6.+- Support aeson 0.8.+- Support criterion 1.0.+- Support transformers 0.4.++# v0.1.1 (2014-10-11)++- Switch PostgreSQL username from "taylor" to "postgres".+ # v0.1.0 (2014-10-11) - Initial release.
README.md view
@@ -1,9 +1,89 @@ # [Hairy][1] -[![Build Status][2]][3]+[![Package version][2]][3]+[![Build status][4]][5]+[![Dependency status][6]][7] -A RESTful CRUD web app.+Hairy is a JSON REST API built in Haskell. It uses Scotty to create a WAI+application served by the Warp web server. The Aeson library handles encoding+and decoding JSON, while Persistent manages the PostgreSQL database. Hairy+features an Hspec test suite and Criterion benchmarks. +The entire project is meant to be easy to build, understand, and use. It doesn't+really do anything useful, but it shows how to do anything at all. Take a look+at [the literate source][8] to see how it all works.++- [Requirements](#requirements)+- [Installation](#installation)+- [Setup](#setup)+- [Configuration](#configuration)++## Requirements++Hairy works best with the latest [Haskell Platform][9], but it also supports GHC+7.8 and 7.6. [PostgreSQL][10] 9.1 or later is also required.++## Installation++Add it to your Cabal file:++```+library+ build-depends:+ hairy ==0.1.*+```++Or install it manually:++``` sh+$ cabal update+$ cabal install hairy-0.1.2+```++This package uses [Semantic Versioning][11].++## Setup++First create a database user for Hairy.++``` sh+$ createuser --createdb postgres+```++Then create databases for each environment.++``` sh+$ psql --username postgres --command 'CREATE DATABASE hairy_development'+$ psql --username postgres --command 'CREATE DATABASE hairy_production'+$ psql --username postgres --command 'CREATE DATABASE hairy_test'+```++Then just start the server!++``` sh+$ hairy+# => http://localhost:3000+```++## Configuration++Hairy can be configured through environment variables. To configure the+environment, use the `SCOTTY_ENV` environment variable.++``` sh+$ env SCOTTY_ENV=Production hairy+```++Possible environments include `Development`, `Production`, and `Test`.+ [1]: https://github.com/tfausak/hairy-[2]: https://travis-ci.org/tfausak/hairy.svg?branch=master-[3]: https://travis-ci.org/tfausak/hairy+[2]: https://img.shields.io/hackage/v/hairy.svg?style=flat+[3]: https://hackage.haskell.org/package/hairy+[4]: https://img.shields.io/travis/tfausak/hairy/master.svg?style=flat+[5]: https://travis-ci.org/tfausak/hairy+[6]: https://img.shields.io/hackage-deps/v/hairy.svg?style=flat+[7]: http://packdeps.haskellers.com/feed?needle=hairy+[8]: ./library/Hairy.lhs+[9]: https://www.haskell.org/platform/+[10]: http://www.postgresql.org+[11]: http://semver.org/spec/v2.0.0.html
hairy.cabal view
@@ -1,5 +1,5 @@ name: hairy-version: 0.1.1+version: 0.1.2 cabal-version: >=1.10 build-type: Simple license: MIT@@ -8,15 +8,15 @@ maintainer: Taylor Fausak <taylor@fausak.me> homepage: https://github.com/tfausak/hairy bug-reports: https://github.com/tfausak/hairy/issues-synopsis: A RESTful CRUD web app.+synopsis: A JSON REST API description:- A RESTful CRUD web app.+ Hairy is a JSON REST API. . Check out <https://github.com/tfausak/hairy#readme the readme> for documentation. category: Web author: Taylor Fausak <taylor@fausak.me>-tested-with: GHC ==7.8.*+tested-with: GHC ==7.6.* GHC ==7.8.* extra-source-files: CHANGELOG.md CONTRIBUTING.md@@ -29,7 +29,7 @@ library build-depends: base ==4.*,- aeson ==0.7.*,+ aeson >=0.7 && <0.9, data-default ==0.5.*, http-types ==0.8.*, mtl ==2.*,@@ -40,7 +40,7 @@ scotty ==0.9.*, text ==1.*, time ==1.*,- transformers ==0.3.*,+ transformers >=0.3 && <0.5, wai ==3.*, wai-extra ==3.*, warp ==3.*@@ -84,7 +84,7 @@ build-depends: base -any, hairy -any,- criterion ==0.8.*,+ criterion >=0.8 && <2, http-types -any, mtl -any, persistent -any,
library/Hairy.lhs view
@@ -1,9 +1,32 @@+Before we can begin, we need to enable a few language extensions.++> {-# LANGUAGE OverloadedStrings #-}++This extension allows string literals (like `"cheese"`) to represent string-like+types such as `ByteString` and `Text`. It's not strictly required since you+could do the same thing using `pack`, for instance. But it's so convenient that+it's hard to live without.+ > {-# LANGUAGE FlexibleContexts #-} > {-# LANGUAGE GeneralizedNewtypeDeriving #-}-> {-# LANGUAGE OverloadedStrings #-} +These are a little harder to explain, so instead I'll explain them when they're+used.++Now we have to let GHC know that our module is called `Hairy`, not `Main` like+it would otherwise assume.+ > module Hairy where +Imports make up the last bit of the preamble. These are a little overly-specific+in order to make it easier to see where everything came from. In the real world+you might import everything from, say, `Web.Scotty.Trans` instead of explicitly+listing everything you needed from it.++For the most part, you don't have to worry about these imports. If you're+curious about something later on, come back up here to see where it's imported+from. Then look it up on Hackage.+ > import Control.Applicative (Applicative) > import Control.Monad.IO.Class (MonadIO, liftIO) > import Control.Monad.Logger (runNoLoggingT, runStdoutLoggingT)@@ -15,7 +38,8 @@ > import qualified Database.Persist as DB > import qualified Database.Persist.Postgresql as DB > import Hairy.Models (Task, TaskId, migrateAll)-> import Network.HTTP.Types.Status (created201, internalServerError500, notFound404)+> import Network.HTTP.Types.Status (created201, internalServerError500,+> notFound404) > import Network.Wai (Middleware) > import Network.Wai.Handler.Warp (defaultSettings) > import Network.Wai.Middleware.RequestLogger (logStdout, logStdoutDev)@@ -86,6 +110,7 @@ > r m = runReaderT (runConfigM m) c > scottyOptsT o r r application +> -- GeneralizedNewtypeDeriving > newtype ConfigM a = ConfigM > { runConfigM :: ReaderT Config IO a > } deriving (Applicative, Functor, Monad, MonadIO, MonadReader Config)@@ -171,6 +196,7 @@ > runDB (DB.delete (toKey i :: TaskId)) > json Null +> -- FlexibleContexts > toKey :: DB.ToBackendKey DB.SqlBackend a => Integer -> DB.Key a > toKey i = DB.toSqlKey (fromIntegral (i :: Integer))