Types + Persistence
This commit is contained in:
commit
c05371b469
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/bower_components/
|
||||
/node_modules/
|
||||
/.pulp-cache/
|
||||
/output/
|
||||
/generated-docs/
|
||||
/.psc*
|
||||
/.purs*
|
||||
/.psa*
|
19
bower.json
Normal file
19
bower.json
Normal 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
121
package-lock.json
generated
Normal 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
18
package.json
Normal 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
9
src/Main.purs
Normal 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!"
|
38
src/SimpleService/Persistence.purs
Normal file
38
src/SimpleService/Persistence.purs
Normal 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)
|
39
src/SimpleService/Types.purs
Normal file
39
src/SimpleService/Types.purs
Normal 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
9
test/Main.purs
Normal 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."
|
Loading…
Reference in New Issue
Block a user