Skip to content

Instantly share code, notes, and snippets.

@Woody88
Created March 21, 2018 20:08
Show Gist options
  • Save Woody88/8ba5b7bf37af92d1e9068650364e0832 to your computer and use it in GitHub Desktop.
Save Woody88/8ba5b7bf37af92d1e9068650364e0832 to your computer and use it in GitHub Desktop.
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
module Haskforce.SForce.Common where
import Data.Text (Text)
import Data.Aeson
import Data.Aeson.Types
import GHC.Generics
import Data.HashMap.Strict as HMS
import Web.HttpApiData (ToHttpApiData(..))
type UrlPath = Text
data SObjectAttr = SObjectAttr
{ sobjectType :: SObjectType
, sobjetUrl :: UrlPath
} deriving (Generic, Show)
data SObject a = SObject
{ attributes :: SObjectAttr
, sobject :: a
} deriving (Generic, Show)
newtype SObjectId = SObjectId Text deriving (Generic, Show)
newtype SObjectType = SObjectType Text deriving (Generic, Show)
{-| data Account = Account
{ accountId :: SObjectId
, name :: Text
}
λ> let x = "{\"attributes\":{\"type\":\"Customerx\",\"url\":\"randoom\"},\"name\":\"Argentina\",\"Id\":\"x01D0000000002RIAQ\"}" :: Data.ByteString.Lazy.Internal.ByteStringlet x = "{\"attributes\":{\"type\":\"Customerx\",\"url\":\"randoom\"},\"name\":\"Argentina\",\"Id\":\"x01D0000000002RIAQ\"}" :: Data.ByteString.Lazy.Internal.ByteString
λ> eitherDecode x :: Either String (SObject Account)
Right (SObject {attributes = SObjectAttr {sobjectType = SObjectType "Customerx", url = "randoom"}, sobject = Account {accountId = SObjectId "x01D0000000002RIAQ", name = "Argentina"}})
|-}
instance ToHttpApiData SObjectId where
toQueryParam (SObjectId id) = id
--- Instance ToJSON definition for all required types
instance ToJSON SObjectId where
toJSON (SObjectId id) = object
["Id" .= id]
--- Instance FromJSON definition for all required types
instance FromJSON SObjectId where
parseJSON = withText "Id" $ \x -> do
return $ SObjectId x
instance FromJSON SObjectType where
parseJSON = withObject "attributes" $ \v -> do
obj <- v .: "type"
return $ SObjectType obj
instance ToJSON SObjectType where
toJSON (SObjectType x) = object
["type" .= x]
instance FromJSON SObjectAttr where
parseJSON (Object o) = do
type_ <- (parseJSON $ (Object o)) :: Parser SObjectType
url_ <- o .: "url"
return $ SObjectAttr type_ url_
instance ToJSON SObjectAttr where
toJSON = genericToJSON defaultOptions
--- Since salesforce return a json attributes object
--- We must execute an operation that extracts the attributes object
--- and parse it using the SObjectAttr FromJSON's parseJSON function
instance FromJSON a => FromJSON (SObject a) where
parseJSON (Object v) = SObject
<$> parseJSON attrJSON
<*> parseJSON sobjectJSON
where (Just attrJSON) = HMS.lookup "attributes" v
sobjectJSON = Object (HMS.delete "attributes" v) :: Value
class SFObject a where
idGetter :: a -> SObjectId
defaultOptId :: String -> Options
defaultOptId s = defaultOptions { fieldLabelModifier = idParser s }
idParser :: String -> (String -> String)
idParser id_ = parser
where parser s
| s == id_ = "Id"
| otherwise = s
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE TypeApplications #-}
module Haskforce.API.Resources (versions, clientSObjectRow, getSFObject, postSFObject) where
import Data.Text
import Data.Proxy
import Data.Aeson (Object, Value)
import Servant.API
import Servant.Client
import Web.HttpApiData
import Haskforce.Types.SForce(Version) --- Need to remove this and add in SForce separate module
import Haskforce.SForce.Common (SObject, SObjectId)
import Haskforce.Types.Utils (AccessToken)
import Haskforce.API.Resources.SObjectRow
import Haskforce.API.Resources.Version
type Data = "data"
type API = Data :> SFVersion
api :: Proxy API
api = Proxy
versions :: Maybe AccessToken -> ClientM [Version]
clientSObjectRow :: HasClient (SObjectRow a) => Proxy a -> Client (SObjectRow a)
clientSObjectRow _ = client (Proxy :: Proxy (SObjectRow a))
(versions) = client api
(getSFObject :<|> postSFObject) = clientSObjectRow (Proxy @ Value)
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeOperators #-}
-- Salesforce SobjectRow API reference link
-- https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_sobject_retrieve.htm
module Haskforce.API.Resources.SObjectRow (SObjectRow(..)) where
import Data.Text
import Servant.API
import Data.Aeson
import Haskforce.SForce.Common (SObject, SObjectId)
-- import Haskforce.Types.SForce (SObject, SFId)
import Haskforce.Types.Utils (AccessToken)
type Data = "data"
type HeaderAuth = Header "Authorization" AccessToken
type SObjectRow a = HeaderAuth :> Capture "sobjectName" Text
:> Capture "id" SObjectId
:> QueryParam "fields" Text
:> Get '[JSON] (SObject a)
:<|> ReqBody '[JSON] a :> Post '[JSON] NoContent
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment