Types + Persistence

master
Abhinav Sarkar 2017-08-28 11:14:37 +05:30
commit c05371b469
8 changed files with 261 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
/bower_components/
/node_modules/
/.pulp-cache/
/output/
/generated-docs/
/.psc*
/.purs*
/.psa*

19
bower.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "ps-simple-rest-service",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"output"
],
"dependencies": {
"purescript-prelude": "^3.1.0",
"purescript-console": "^3.0.0",
"purescript-foreign-generic": "^5.0.0",
"purescript-postgresql-client": "^2.1.0",
"purescript-aff": "^3.1.0"
},
"devDependencies": {
"purescript-psci-support": "^3.0.0"
}
}

121
package-lock.json generated Normal file
View File

@ -0,0 +1,121 @@
{
"name": "ps-simple-rest-service",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"buffer-writer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz",
"integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg="
},
"generic-pool": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz",
"integrity": "sha1-eAw29p360FpaBF3Te+etyhGk9v8="
},
"object-assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
"integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A="
},
"packet-reader": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz",
"integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc="
},
"pg": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-6.4.0.tgz",
"integrity": "sha1-y3a6Lnwuq4n8ZL96n+ZIztckNtw=",
"requires": {
"buffer-writer": "1.0.1",
"packet-reader": "0.3.1",
"pg-connection-string": "0.1.3",
"pg-pool": "1.8.0",
"pg-types": "1.12.1",
"pgpass": "1.0.2",
"semver": "4.3.2"
}
},
"pg-connection-string": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz",
"integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc="
},
"pg-pool": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-1.8.0.tgz",
"integrity": "sha1-9+xzgkw3oD8Hb1G/33DjQBR8Tzc=",
"requires": {
"generic-pool": "2.4.3",
"object-assign": "4.1.0"
}
},
"pg-types": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz",
"integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=",
"requires": {
"postgres-array": "1.0.2",
"postgres-bytea": "1.0.0",
"postgres-date": "1.0.3",
"postgres-interval": "1.1.1"
}
},
"pgpass": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz",
"integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=",
"requires": {
"split": "1.0.1"
}
},
"postgres-array": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.2.tgz",
"integrity": "sha1-jgsy6wO/d6XAp4UeBEHBaaJWojg="
},
"postgres-bytea": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
},
"postgres-date": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz",
"integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g="
},
"postgres-interval": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.1.tgz",
"integrity": "sha512-OkuCi9t/3CZmeQreutGgx/OVNv9MKHGIT5jH8KldQ4NLYXkvmT9nDVxEuCENlNwhlGPE374oA/xMqn05G49pHA==",
"requires": {
"xtend": "4.0.1"
}
},
"semver": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
"integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
},
"split": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
"requires": {
"through": "2.3.8"
}
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
},
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
}
}
}

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "ps-simple-rest-service",
"version": "1.0.0",
"description": "",
"main": "index.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"pg": "^6.4.0"
}
}

9
src/Main.purs Normal file
View File

@ -0,0 +1,9 @@
module Main where
import Prelude
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
main :: forall e. Eff (console :: CONSOLE | e) Unit
main = do
log "Hello sailor!"

View File

@ -0,0 +1,38 @@
module SimpleServer.Persistence
( insertUser
, findUser
, updateUser
, deleteUser
) where
import Prelude
import Control.Monad.Aff (Aff)
import Data.Array as Array
import Data.Maybe (Maybe)
import Database.PostgreSQL as PG
import SimpleServer.Types (User(..), UserID)
insertUserQuery :: String
insertUserQuery = "insert into users (id, name) values ($1, $2)"
findUserQuery :: String
findUserQuery = "select id, name from users where id = $1"
updateUserQuery :: String
updateUserQuery = "update users set name = $1 where id = $2"
deleteUserQuery :: String
deleteUserQuery = "delete from users where id = $1"
insertUser :: forall eff. PG.Connection -> User -> Aff (postgreSQL :: PG.POSTGRESQL | eff) Unit
insertUser conn user = PG.execute conn (PG.Query insertUserQuery) user
findUser :: forall eff. PG.Connection -> UserID -> Aff (postgreSQL :: PG.POSTGRESQL | eff) (Maybe User)
findUser conn userID = map Array.head $ PG.query conn (PG.Query findUserQuery) (PG.Row1 userID)
updateUser :: forall eff. PG.Connection -> User -> Aff (postgreSQL :: PG.POSTGRESQL | eff) Unit
updateUser conn (User {id, name}) = PG.execute conn (PG.Query updateUserQuery) (PG.Row2 name id)
deleteUser :: forall eff. PG.Connection -> UserID -> Aff (postgreSQL :: PG.POSTGRESQL | eff) Unit
deleteUser conn userID = PG.execute conn (PG.Query deleteUserQuery) (PG.Row1 userID)

View File

@ -0,0 +1,39 @@
module SimpleServer.Types where
import Prelude
import Data.Array as Array
import Data.Either (Either(..))
import Data.Foreign.Class (class Decode, class Encode)
import Data.Foreign.Generic (defaultOptions, genericDecode, genericEncode)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Database.PostgreSQL (class FromSQLRow, class ToSQLRow, fromSQLValue, toSQLValue)
type UserID = Int
newtype User = User
{ id :: UserID
, name :: String
}
derive instance genericUser :: Generic User _
instance showUser :: Show User where
show = genericShow
instance decodeUser :: Decode User where
decode = genericDecode $ defaultOptions { unwrapSingleConstructors = true }
instance encodeUser :: Encode User where
encode = genericEncode $ defaultOptions { unwrapSingleConstructors = true }
instance userFromSQLRow :: FromSQLRow User where
fromSQLRow [id, name] =
User <$> ({ id: _, name: _} <$> fromSQLValue id <*> fromSQLValue name)
fromSQLRow xs = Left $ "Row has " <> show n <> " fields, expecting 2."
where n = Array.length xs
instance userToSQLRow :: ToSQLRow User where
toSQLRow (User {id, name}) = [toSQLValue id, toSQLValue name]

9
test/Main.purs Normal file
View File

@ -0,0 +1,9 @@
module Test.Main where
import Prelude
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
main :: forall e. Eff (console :: CONSOLE | e) Unit
main = do
log "You should add some tests."