diff --git a/src/AWS/Core/Credentials.js b/src/AWS/Core/Credentials.js new file mode 100644 index 0000000..3b71fcd --- /dev/null +++ b/src/AWS/Core/Credentials.js @@ -0,0 +1,5 @@ +"use strict" + +var AWS = require('aws-sdk') + +exports.newSharedIniFileCredentials = (params) => () => new AWS.SharedIniFileCredentials(params) diff --git a/src/AWS/Core/Credentials.purs b/src/AWS/Core/Credentials.purs new file mode 100644 index 0000000..fe4d7b4 --- /dev/null +++ b/src/AWS/Core/Credentials.purs @@ -0,0 +1,6 @@ +module AWS.Core.Credentials where + +import AWS.Core.Types (Credentials) +import Effect (Effect) + +foreign import newSharedIniFileCredentials :: { profile :: String } -> Effect Credentials diff --git a/src/AWS/Core/Types.purs b/src/AWS/Core/Types.purs index aea1b63..3b729b6 100644 --- a/src/AWS/Core/Types.purs +++ b/src/AWS/Core/Types.purs @@ -1,9 +1,10 @@ module AWS.Core.Types where -import Prelude (class Show) +import Data.Maybe (Maybe) import Data.Newtype (class Newtype) +import Foreign (Foreign, tagOf) +import Prelude (class Show) import Simple.JSON (class WriteForeign) -import Data.Maybe (Maybe) newtype AccessKeyId = AccessKeyId String @@ -60,11 +61,23 @@ derive instance ntInstanceType :: Newtype InstanceType _ derive newtype instance showInstanceType :: Show InstanceType +newtype Credentials + = Credentials Foreign + +derive instance ntCredentials :: Newtype Credentials _ + +instance showCredentials :: Show Credentials where + show (Credentials credentials) = tagOf credentials + +instance writeCreds :: WriteForeign Credentials where + writeImpl (Credentials creds) = creds + type BasicClientPropsR r = ( accessKeyId :: Maybe AccessKeyId , secretAccessKey :: Maybe SecretAccessKey , region :: Maybe Region , sessionToken :: Maybe SessionToken + , credentials :: (Maybe Credentials) | r ) diff --git a/src/AWS/Core/Util.purs b/src/AWS/Core/Util.purs index ce9c9d9..21e18be 100644 --- a/src/AWS/Core/Util.purs +++ b/src/AWS/Core/Util.purs @@ -1,13 +1,13 @@ module AWS.Core.Util where import Prelude -import Control.Monad.Error.Class (class MonadThrow, throwError) +import Control.Monad.Error.Class (class MonadError, class MonadThrow, catchError, throwError) import Data.DateTime (DateTime) -import Data.Either (Either, either) +import Data.Either (Either(..), either) import Data.Formatter.DateTime (formatDateTime) -import Effect.Exception (Error, error) import Data.Nullable (Nullable, toMaybe) import Data.Unfoldable (fromMaybe) +import Effect.Exception (Error, error) toIso8601Date :: DateTime -> Either String String toIso8601Date d = formatDateTime "YYYY-MM-DD" d @@ -20,3 +20,6 @@ joinNullArr = nullToArr >>> join nullToArr :: forall a. Nullable a -> Array a nullToArr = toMaybe >>> fromMaybe + +catchAwsError :: forall m e s. MonadError e m => m (Either e s) -> m (Either e s) +catchAwsError = (flip catchError) (Left >>> pure) diff --git a/src/AWS/DynamoDB/DynamoDb.js b/src/AWS/DynamoDB/DynamoDb.js new file mode 100644 index 0000000..d67e955 --- /dev/null +++ b/src/AWS/DynamoDB/DynamoDb.js @@ -0,0 +1,11 @@ +"use strict" + +var AWS = require('aws-sdk') + +exports.newDynamoDbClient = (params) => () => new AWS.DynamoDB(params) + +exports.getItemImpl = (db, params) => () => db.getItem(params).promise() + +exports.putItemImpl = (db, params) => () => db.putItem(params).promise() + +exports.createTableImpl = (db, params) => () => db.createTable(params).promise() diff --git a/src/AWS/DynamoDB/DynamoDb.purs b/src/AWS/DynamoDB/DynamoDb.purs new file mode 100644 index 0000000..c1ca553 --- /dev/null +++ b/src/AWS/DynamoDB/DynamoDb.purs @@ -0,0 +1,97 @@ +module AWS.DynamoDb where + +import Prelude +import AWS.Core.Client (makeClientHelper) +import AWS.Core.Types (DefaultClientProps) +import AWS.Core.Util (catchAwsError) +import Control.Promise (Promise) +import Control.Promise as Promise +import Data.Either (Either(..)) +import Data.Function.Uncurried (Fn2, runFn2) +import Data.Maybe (Maybe(..)) +import Data.Nullable (Nullable) +import Data.Nullable as Nullable +import Effect (Effect) +import Effect.Aff (Aff, Error, catchError) +import Effect.Class (liftEffect) +import Foreign (Foreign) +import Justifill (justifillVia) +import Justifill.Fillable (class Fillable) +import Justifill.Justifiable (class Justifiable) +import Type.Proxy (Proxy(..)) + +foreign import data DynamoDbClient :: Type + +foreign import newDynamoDbClient :: Foreign -> (Effect DynamoDbClient) + +makeClient :: + forall r via. + Justifiable { | r } { | via } => + Fillable { | via } DefaultClientProps => + { | r } -> + Effect DynamoDbClient +makeClient r = makeClientHelper newDynamoDbClient props + where + viaProxy :: Proxy { | via } + viaProxy = Proxy + + props :: DefaultClientProps + props = justifillVia viaProxy r + +type GetItemInput input key + = { "TableName" :: String, "Key" :: Record key | input } + +type PutItemInput input item + = { "TableName" :: String, "Item" :: Record item | input } + +type InternalGetItemOutput output + = { "Item" :: Nullable output } + +type GetItemOutput output + = { item :: Maybe output } + +foreign import getItemImpl :: forall input key output. Fn2 DynamoDbClient (GetItemInput input key) (Effect (Promise (InternalGetItemOutput output))) + +getItem :: forall input key output. DynamoDbClient -> (GetItemInput input key) -> Aff (Either Error (GetItemOutput output)) +getItem client input = liftEffect (curried client input) >>= Promise.toAff <#> toExternal # catchAwsError + where + toExternal response = + { item: Nullable.toMaybe response."Item" } + # Right + + curried = runFn2 getItemImpl + +foreign import putItemImpl :: forall input item. Fn2 DynamoDbClient (PutItemInput input item) (Effect (Promise Unit)) + +putItem :: forall input item. DynamoDbClient -> (PutItemInput input item) -> Aff (Maybe Error) +putItem client input = liftEffect (curried client input) >>= Promise.toAff <#> toExternal # (flip catchError) (Just >>> pure) + where + toExternal response = Nothing + + curried = runFn2 putItemImpl + +type KeySchemaElement + = { "AttributeName" :: String + , "KeyType" :: String + } + +type AttributeDefinition + = { "AttributeName" :: String + , "AttributeType" :: String + } + +type CreateTableInput input + = { "AttributeDefinitions" :: Array AttributeDefinition + , "TableName" :: String + , "KeySchema" :: Array KeySchemaElement + | input + } + +foreign import createTableImpl :: forall input. Fn2 DynamoDbClient (CreateTableInput input) (Effect (Promise Unit)) + +createTable :: forall input. DynamoDbClient -> (CreateTableInput input) -> Aff (Maybe Error) +createTable client input = liftEffect (curried client input) >>= Promise.toAff <#> toExternal # (flip catchError) (Just >>> pure) + where + toExternal response = Nothing + + curried = runFn2 createTableImpl