packages feed

pinboard 0.8.10 → 0.9.0

raw patch · 12 files changed

+332/−323 lines, 12 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Pinboard.ApiTypes: fromDoneResult :: DoneResult -> ()
- Pinboard.ApiTypes: fromJsonTagMap :: JsonTagMap -> TagMap
- Pinboard.ApiTypes: fromTextResult :: TextResult -> Text
- Pinboard.ApiTypes: fromUpdateTime :: UpdateTime -> UTCTime
- Pinboard.ApiTypes: instance Data DoneResult
- Pinboard.ApiTypes: instance Data JsonTagMap
- Pinboard.ApiTypes: instance Data Note
- Pinboard.ApiTypes: instance Data NoteList
- Pinboard.ApiTypes: instance Data NoteListItem
- Pinboard.ApiTypes: instance Data Post
- Pinboard.ApiTypes: instance Data PostDates
- Pinboard.ApiTypes: instance Data Posts
- Pinboard.ApiTypes: instance Data Suggested
- Pinboard.ApiTypes: instance Data TextResult
- Pinboard.ApiTypes: instance Data UpdateTime
- Pinboard.ApiTypes: instance Eq DoneResult
- Pinboard.ApiTypes: instance Eq JsonTagMap
- Pinboard.ApiTypes: instance Eq Note
- Pinboard.ApiTypes: instance Eq NoteList
- Pinboard.ApiTypes: instance Eq NoteListItem
- Pinboard.ApiTypes: instance Eq Post
- Pinboard.ApiTypes: instance Eq PostDates
- Pinboard.ApiTypes: instance Eq Posts
- Pinboard.ApiTypes: instance Eq Suggested
- Pinboard.ApiTypes: instance Eq TextResult
- Pinboard.ApiTypes: instance Eq UpdateTime
- Pinboard.ApiTypes: instance FromJSON DoneResult
- Pinboard.ApiTypes: instance FromJSON JsonTagMap
- Pinboard.ApiTypes: instance FromJSON Note
- Pinboard.ApiTypes: instance FromJSON NoteList
- Pinboard.ApiTypes: instance FromJSON NoteListItem
- Pinboard.ApiTypes: instance FromJSON Post
- Pinboard.ApiTypes: instance FromJSON PostDates
- Pinboard.ApiTypes: instance FromJSON Posts
- Pinboard.ApiTypes: instance FromJSON Suggested
- Pinboard.ApiTypes: instance FromJSON TextResult
- Pinboard.ApiTypes: instance FromJSON UpdateTime
- Pinboard.ApiTypes: instance Ord DoneResult
- Pinboard.ApiTypes: instance Ord Note
- Pinboard.ApiTypes: instance Ord NoteList
- Pinboard.ApiTypes: instance Ord NoteListItem
- Pinboard.ApiTypes: instance Ord Post
- Pinboard.ApiTypes: instance Ord PostDates
- Pinboard.ApiTypes: instance Ord Posts
- Pinboard.ApiTypes: instance Ord Suggested
- Pinboard.ApiTypes: instance Ord TextResult
- Pinboard.ApiTypes: instance Ord UpdateTime
- Pinboard.ApiTypes: instance Show DoneResult
- Pinboard.ApiTypes: instance Show JsonTagMap
- Pinboard.ApiTypes: instance Show Note
- Pinboard.ApiTypes: instance Show NoteList
- Pinboard.ApiTypes: instance Show NoteListItem
- Pinboard.ApiTypes: instance Show Post
- Pinboard.ApiTypes: instance Show PostDates
- Pinboard.ApiTypes: instance Show Posts
- Pinboard.ApiTypes: instance Show Suggested
- Pinboard.ApiTypes: instance Show TextResult
- Pinboard.ApiTypes: instance Show UpdateTime
- Pinboard.ApiTypes: instance ToJSON JsonTagMap
- Pinboard.ApiTypes: instance ToJSON Note
- Pinboard.ApiTypes: instance ToJSON NoteList
- Pinboard.ApiTypes: instance ToJSON NoteListItem
- Pinboard.ApiTypes: instance ToJSON Post
- Pinboard.ApiTypes: instance ToJSON PostDates
- Pinboard.ApiTypes: instance ToJSON Posts
- Pinboard.ApiTypes: instance ToJSON Suggested
- Pinboard.ApiTypes: instance ToJSON [Suggested]
- Pinboard.ApiTypes: instance Typeable DoneResult
- Pinboard.ApiTypes: instance Typeable JsonTagMap
- Pinboard.ApiTypes: instance Typeable Note
- Pinboard.ApiTypes: instance Typeable NoteList
- Pinboard.ApiTypes: instance Typeable NoteListItem
- Pinboard.ApiTypes: instance Typeable Post
- Pinboard.ApiTypes: instance Typeable PostDates
- Pinboard.ApiTypes: instance Typeable Posts
- Pinboard.ApiTypes: instance Typeable Suggested
- Pinboard.ApiTypes: instance Typeable TextResult
- Pinboard.ApiTypes: instance Typeable UpdateTime
- Pinboard.ApiTypes: noteCreatedAt :: Note -> UTCTime
- Pinboard.ApiTypes: noteHash :: Note -> Text
- Pinboard.ApiTypes: noteId :: Note -> Text
- Pinboard.ApiTypes: noteLength :: Note -> Int
- Pinboard.ApiTypes: noteListCount :: NoteList -> Int
- Pinboard.ApiTypes: noteListItemCreatedAt :: NoteListItem -> UTCTime
- Pinboard.ApiTypes: noteListItemHash :: NoteListItem -> Text
- Pinboard.ApiTypes: noteListItemId :: NoteListItem -> Text
- Pinboard.ApiTypes: noteListItemLength :: NoteListItem -> Int
- Pinboard.ApiTypes: noteListItemTitle :: NoteListItem -> Text
- Pinboard.ApiTypes: noteListItemUpdatedAt :: NoteListItem -> UTCTime
- Pinboard.ApiTypes: noteListItems :: NoteList -> [NoteListItem]
- Pinboard.ApiTypes: noteText :: Note -> Text
- Pinboard.ApiTypes: noteTitle :: Note -> Text
- Pinboard.ApiTypes: noteUpdatedAt :: Note -> UTCTime
- Pinboard.ApiTypes: postDatesCount :: PostDates -> [DateCount]
- Pinboard.ApiTypes: postDatesTag :: PostDates -> Text
- Pinboard.ApiTypes: postDatesUser :: PostDates -> Text
- Pinboard.ApiTypes: postDescription :: Post -> Text
- Pinboard.ApiTypes: postExtended :: Post -> Text
- Pinboard.ApiTypes: postHash :: Post -> Text
- Pinboard.ApiTypes: postHref :: Post -> Text
- Pinboard.ApiTypes: postMeta :: Post -> Text
- Pinboard.ApiTypes: postShared :: Post -> Bool
- Pinboard.ApiTypes: postTags :: Post -> [Tag]
- Pinboard.ApiTypes: postTime :: Post -> UTCTime
- Pinboard.ApiTypes: postToread :: Post -> Bool
- Pinboard.ApiTypes: postsDate :: Posts -> UTCTime
- Pinboard.ApiTypes: postsPosts :: Posts -> [Post]
- Pinboard.ApiTypes: postsUser :: Posts -> Text
- Pinboard.Client: apiToken :: PinboardConfig -> ByteString
- Pinboard.Client: debug :: PinboardConfig -> Bool
- Pinboard.Client: mgrOpen :: MonadIO m => m (Either SomeException Manager)
- Pinboard.Client: mgrOpenRaw :: MonadIO m => m Manager
- Pinboard.Client.Error: BadRequest :: PinboardErrorHTTPCode
- Pinboard.Client.Error: ConnectionFailure :: PinboardErrorType
- Pinboard.Client.Error: Forbidden :: PinboardErrorHTTPCode
- Pinboard.Client.Error: HttpStatusFailure :: PinboardErrorType
- Pinboard.Client.Error: NotFound :: PinboardErrorHTTPCode
- Pinboard.Client.Error: ParseFailure :: PinboardErrorType
- Pinboard.Client.Error: PinboardError :: PinboardErrorType -> Text -> Maybe PinboardErrorCode -> Maybe Text -> Maybe PinboardErrorHTTPCode -> PinboardError
- Pinboard.Client.Error: PinboardServerError :: PinboardErrorHTTPCode
- Pinboard.Client.Error: RequestFailed :: PinboardErrorHTTPCode
- Pinboard.Client.Error: TooManyRequests :: PinboardErrorHTTPCode
- Pinboard.Client.Error: UnAuthorized :: PinboardErrorHTTPCode
- Pinboard.Client.Error: UnknownError :: PinboardErrorCode
- Pinboard.Client.Error: UnknownErrorType :: PinboardErrorType
- Pinboard.Client.Error: UnknownHTTPCode :: PinboardErrorHTTPCode
- Pinboard.Client.Error: data PinboardError
- Pinboard.Client.Error: data PinboardErrorCode
- Pinboard.Client.Error: data PinboardErrorHTTPCode
- Pinboard.Client.Error: data PinboardErrorType
- Pinboard.Client.Error: defaultPinboardError :: PinboardError
- Pinboard.Client.Error: errorCode :: PinboardError -> Maybe PinboardErrorCode
- Pinboard.Client.Error: errorHTTP :: PinboardError -> Maybe PinboardErrorHTTPCode
- Pinboard.Client.Error: errorMsg :: PinboardError -> Text
- Pinboard.Client.Error: errorParam :: PinboardError -> Maybe Text
- Pinboard.Client.Error: errorType :: PinboardError -> PinboardErrorType
- Pinboard.Client.Error: instance Show PinboardError
- Pinboard.Client.Error: instance Show PinboardErrorCode
- Pinboard.Client.Error: instance Show PinboardErrorHTTPCode
- Pinboard.Client.Error: instance Show PinboardErrorType
- Pinboard.Client.Types: Count :: Int -> Param
- Pinboard.Client.Types: Date :: Day -> Param
- Pinboard.Client.Types: DateTime :: UTCTime -> Param
- Pinboard.Client.Types: Description :: Text -> Param
- Pinboard.Client.Types: Extended :: Text -> Param
- Pinboard.Client.Types: Format :: ResultFormatType -> Param
- Pinboard.Client.Types: FormatJson :: ResultFormatType
- Pinboard.Client.Types: FormatXml :: ResultFormatType
- Pinboard.Client.Types: FromDateTime :: UTCTime -> Param
- Pinboard.Client.Types: Meta :: Int -> Param
- Pinboard.Client.Types: New :: Text -> Param
- Pinboard.Client.Types: Old :: Text -> Param
- Pinboard.Client.Types: PinboardConfig :: ByteString -> Bool -> PinboardConfig
- Pinboard.Client.Types: PinboardRequest :: Text -> [Param] -> PinboardRequest
- Pinboard.Client.Types: Replace :: Bool -> Param
- Pinboard.Client.Types: Results :: Int -> Param
- Pinboard.Client.Types: Shared :: Bool -> Param
- Pinboard.Client.Types: Start :: Int -> Param
- Pinboard.Client.Types: Tag :: Text -> Param
- Pinboard.Client.Types: Tags :: Text -> Param
- Pinboard.Client.Types: ToDateTime :: UTCTime -> Param
- Pinboard.Client.Types: ToRead :: Bool -> Param
- Pinboard.Client.Types: Url :: Text -> Param
- Pinboard.Client.Types: apiToken :: PinboardConfig -> ByteString
- Pinboard.Client.Types: data Param
- Pinboard.Client.Types: data PinboardConfig
- Pinboard.Client.Types: data PinboardRequest
- Pinboard.Client.Types: data ResultFormatType
- Pinboard.Client.Types: debug :: PinboardConfig -> Bool
- Pinboard.Client.Types: instance Eq Param
- Pinboard.Client.Types: instance Eq ResultFormatType
- Pinboard.Client.Types: instance Show Param
- Pinboard.Client.Types: instance Show PinboardConfig
- Pinboard.Client.Types: instance Show PinboardRequest
- Pinboard.Client.Types: instance Show ResultFormatType
- Pinboard.Client.Types: requestParams :: PinboardRequest -> [Param]
- Pinboard.Client.Types: requestPath :: PinboardRequest -> Text
- Pinboard.Client.Types: runPinboardT :: PinboardEnv -> PinboardT m a -> m (Either PinboardError a)
- Pinboard.Client.Types: type MonadPinboard m = (Functor m, Applicative m, Monad m, MonadIO m, MonadIO m, MonadReader PinboardEnv m, MonadError PinboardError m)
- Pinboard.Client.Types: type ParamsBS = [(ByteString, ByteString)]
- Pinboard.Client.Types: type PinboardEnv = (PinboardConfig, Manager)
- Pinboard.Client.Types: type PinboardT m a = ReaderT PinboardEnv (ExceptT PinboardError m) a
- Pinboard.Client.Util: (</>) :: (Monoid m, IsString m) => m -> m -> m
- Pinboard.Client.Util: encodeParams :: [Param] -> ParamsBS
- Pinboard.Client.Util: ensureResultFormatType :: ResultFormatType -> PinboardRequest -> PinboardRequest
- Pinboard.Client.Util: mkConfig :: PinboardConfig
- Pinboard.Client.Util: paramToName :: Param -> Text
- Pinboard.Client.Util: paramToText :: Param -> (Text, Text)
- Pinboard.Client.Util: paramsToByteString :: (Monoid m, IsString m) => [(m, m)] -> m
- Pinboard.Client.Util: toText :: Show a => a -> Text
- Pinboard.Client.Util: toTextLower :: Show a => a -> Text
+ Pinboard.ApiTypes: [fromDoneResult] :: DoneResult -> ()
+ Pinboard.ApiTypes: [fromJsonTagMap] :: JsonTagMap -> TagMap
+ Pinboard.ApiTypes: [fromTextResult] :: TextResult -> Text
+ Pinboard.ApiTypes: [fromUpdateTime] :: UpdateTime -> UTCTime
+ Pinboard.ApiTypes: [noteCreatedAt] :: Note -> UTCTime
+ Pinboard.ApiTypes: [noteHash] :: Note -> Text
+ Pinboard.ApiTypes: [noteId] :: Note -> Text
+ Pinboard.ApiTypes: [noteLength] :: Note -> Int
+ Pinboard.ApiTypes: [noteListCount] :: NoteList -> Int
+ Pinboard.ApiTypes: [noteListItemCreatedAt] :: NoteListItem -> UTCTime
+ Pinboard.ApiTypes: [noteListItemHash] :: NoteListItem -> Text
+ Pinboard.ApiTypes: [noteListItemId] :: NoteListItem -> Text
+ Pinboard.ApiTypes: [noteListItemLength] :: NoteListItem -> Int
+ Pinboard.ApiTypes: [noteListItemTitle] :: NoteListItem -> Text
+ Pinboard.ApiTypes: [noteListItemUpdatedAt] :: NoteListItem -> UTCTime
+ Pinboard.ApiTypes: [noteListItems] :: NoteList -> [NoteListItem]
+ Pinboard.ApiTypes: [noteText] :: Note -> Text
+ Pinboard.ApiTypes: [noteTitle] :: Note -> Text
+ Pinboard.ApiTypes: [noteUpdatedAt] :: Note -> UTCTime
+ Pinboard.ApiTypes: [postDatesCount] :: PostDates -> [DateCount]
+ Pinboard.ApiTypes: [postDatesTag] :: PostDates -> Text
+ Pinboard.ApiTypes: [postDatesUser] :: PostDates -> Text
+ Pinboard.ApiTypes: [postDescription] :: Post -> Text
+ Pinboard.ApiTypes: [postExtended] :: Post -> Text
+ Pinboard.ApiTypes: [postHash] :: Post -> Text
+ Pinboard.ApiTypes: [postHref] :: Post -> Text
+ Pinboard.ApiTypes: [postMeta] :: Post -> Text
+ Pinboard.ApiTypes: [postShared] :: Post -> Bool
+ Pinboard.ApiTypes: [postTags] :: Post -> [Tag]
+ Pinboard.ApiTypes: [postTime] :: Post -> UTCTime
+ Pinboard.ApiTypes: [postToread] :: Post -> Bool
+ Pinboard.ApiTypes: [postsDate] :: Posts -> UTCTime
+ Pinboard.ApiTypes: [postsPosts] :: Posts -> [Post]
+ Pinboard.ApiTypes: [postsUser] :: Posts -> Text
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.UpdateTime
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON [Pinboard.ApiTypes.Suggested]
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.UpdateTime
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.UpdateTime
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.UpdateTime
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.UpdateTime
+ Pinboard.Client: [apiToken] :: PinboardConfig -> ByteString
+ Pinboard.Client: [debug] :: PinboardConfig -> Bool
+ Pinboard.Client: newMgr :: MonadIO m => m Manager
+ Pinboard.Error: BadRequest :: PinboardErrorHTTPCode
+ Pinboard.Error: ConnectionFailure :: PinboardErrorType
+ Pinboard.Error: Forbidden :: PinboardErrorHTTPCode
+ Pinboard.Error: HttpStatusFailure :: PinboardErrorType
+ Pinboard.Error: NotFound :: PinboardErrorHTTPCode
+ Pinboard.Error: ParseFailure :: PinboardErrorType
+ Pinboard.Error: PinboardError :: PinboardErrorType -> Text -> Maybe PinboardErrorCode -> Maybe Text -> Maybe PinboardErrorHTTPCode -> PinboardError
+ Pinboard.Error: PinboardServerError :: PinboardErrorHTTPCode
+ Pinboard.Error: RequestFailed :: PinboardErrorHTTPCode
+ Pinboard.Error: TooManyRequests :: PinboardErrorHTTPCode
+ Pinboard.Error: UnAuthorized :: PinboardErrorHTTPCode
+ Pinboard.Error: UnknownError :: PinboardErrorCode
+ Pinboard.Error: UnknownErrorType :: PinboardErrorType
+ Pinboard.Error: UnknownHTTPCode :: PinboardErrorHTTPCode
+ Pinboard.Error: [errorCode] :: PinboardError -> Maybe PinboardErrorCode
+ Pinboard.Error: [errorHTTP] :: PinboardError -> Maybe PinboardErrorHTTPCode
+ Pinboard.Error: [errorMsg] :: PinboardError -> Text
+ Pinboard.Error: [errorParam] :: PinboardError -> Maybe Text
+ Pinboard.Error: [errorType] :: PinboardError -> PinboardErrorType
+ Pinboard.Error: data PinboardError
+ Pinboard.Error: data PinboardErrorCode
+ Pinboard.Error: data PinboardErrorHTTPCode
+ Pinboard.Error: data PinboardErrorType
+ Pinboard.Error: defaultPinboardError :: PinboardError
+ Pinboard.Error: instance GHC.Show.Show Pinboard.Error.PinboardError
+ Pinboard.Error: instance GHC.Show.Show Pinboard.Error.PinboardErrorCode
+ Pinboard.Error: instance GHC.Show.Show Pinboard.Error.PinboardErrorHTTPCode
+ Pinboard.Error: instance GHC.Show.Show Pinboard.Error.PinboardErrorType
+ Pinboard.Types: Count :: Int -> Param
+ Pinboard.Types: Date :: Day -> Param
+ Pinboard.Types: DateTime :: UTCTime -> Param
+ Pinboard.Types: Description :: Text -> Param
+ Pinboard.Types: Extended :: Text -> Param
+ Pinboard.Types: Format :: ResultFormatType -> Param
+ Pinboard.Types: FormatJson :: ResultFormatType
+ Pinboard.Types: FormatXml :: ResultFormatType
+ Pinboard.Types: FromDateTime :: UTCTime -> Param
+ Pinboard.Types: Meta :: Int -> Param
+ Pinboard.Types: New :: Text -> Param
+ Pinboard.Types: Old :: Text -> Param
+ Pinboard.Types: PinboardConfig :: ByteString -> Bool -> PinboardConfig
+ Pinboard.Types: PinboardRequest :: Text -> [Param] -> PinboardRequest
+ Pinboard.Types: Replace :: Bool -> Param
+ Pinboard.Types: Results :: Int -> Param
+ Pinboard.Types: Shared :: Bool -> Param
+ Pinboard.Types: Start :: Int -> Param
+ Pinboard.Types: Tag :: Text -> Param
+ Pinboard.Types: Tags :: Text -> Param
+ Pinboard.Types: ToDateTime :: UTCTime -> Param
+ Pinboard.Types: ToRead :: Bool -> Param
+ Pinboard.Types: Url :: Text -> Param
+ Pinboard.Types: [apiToken] :: PinboardConfig -> ByteString
+ Pinboard.Types: [debug] :: PinboardConfig -> Bool
+ Pinboard.Types: [requestParams] :: PinboardRequest -> [Param]
+ Pinboard.Types: [requestPath] :: PinboardRequest -> Text
+ Pinboard.Types: data Param
+ Pinboard.Types: data PinboardConfig
+ Pinboard.Types: data PinboardRequest
+ Pinboard.Types: data ResultFormatType
+ Pinboard.Types: instance GHC.Classes.Eq Pinboard.Types.Param
+ Pinboard.Types: instance GHC.Classes.Eq Pinboard.Types.ResultFormatType
+ Pinboard.Types: instance GHC.Show.Show Pinboard.Types.Param
+ Pinboard.Types: instance GHC.Show.Show Pinboard.Types.PinboardConfig
+ Pinboard.Types: instance GHC.Show.Show Pinboard.Types.PinboardRequest
+ Pinboard.Types: instance GHC.Show.Show Pinboard.Types.ResultFormatType
+ Pinboard.Types: runPinboardT :: PinboardEnv -> PinboardT m a -> m (Either PinboardError a)
+ Pinboard.Types: type MonadPinboard m = (Functor m, Applicative m, Monad m, MonadIO m, MonadReader PinboardEnv m, MonadError PinboardError m)
+ Pinboard.Types: type ParamsBS = [(ByteString, ByteString)]
+ Pinboard.Types: type PinboardEnv = (PinboardConfig, Manager)
+ Pinboard.Types: type PinboardT m a = ReaderT PinboardEnv (ExceptT PinboardError m) a
+ Pinboard.Util: (</>) :: (Monoid m, IsString m) => m -> m -> m
+ Pinboard.Util: encodeParams :: [Param] -> ParamsBS
+ Pinboard.Util: ensureResultFormatType :: ResultFormatType -> PinboardRequest -> PinboardRequest
+ Pinboard.Util: mkConfig :: PinboardConfig
+ Pinboard.Util: paramToName :: Param -> Text
+ Pinboard.Util: paramToText :: Param -> (Text, Text)
+ Pinboard.Util: paramsToByteString :: (Monoid m, IsString m) => [(m, m)] -> m
+ Pinboard.Util: toText :: Show a => a -> Text
+ Pinboard.Util: toTextLower :: Show a => a -> Text
- Pinboard.Client: runPinboardSingleRaw :: MonadIO m => PinboardConfig -> PinboardRequest -> (Response ByteString -> a) -> m (Either PinboardError a)
+ Pinboard.Client: runPinboardSingleRaw :: MonadIO m => PinboardConfig -> PinboardRequest -> m (Either PinboardError (Response ByteString))
- Pinboard.Client: sendPinboardRequest :: MonadIO m => PinboardEnv -> PinboardRequest -> (Response ByteString -> a) -> m a
+ Pinboard.Client: sendPinboardRequest :: MonadIO m => PinboardEnv -> PinboardRequest -> m (Response ByteString)

Files

README.md view
@@ -28,7 +28,27 @@     Right details -> print details     Left pinboardError -> print pinboardError ```++output:+```+Posts{postsDate = 2015 - 10 - 24 16 : 17 : 12 UTC,+       postsUser = "jonschoning",+       postsPosts =+         [Post{postHref = "http://www.reddit.com/r/haskell/comments/25vj62/adventure_with_types_in_haskell_simon_peyton/",+               postDescription = "Adventure with Types in Haskell - Simon Peyton Jones [1:33:36] : haskell",+               postExtended = "", +               postMeta = "3fe9fb05c7c37f7bb66be7b9d85599eb",+               postHash = "c46b717604ef8b126dabeba97b27a36f",+               postTime = 2014 - 5 - 19 3 : 35 : 55 UTC, +               postShared = True,+               postToread = False,+               postTags = ["spj", "video", "haskell", "typetheory"]}]}+``` ## Modules++[Pinboard.Types](https://hackage.haskell.org/package/pinboard/docs/Pinboard-Types.html)++  Pinboard typeclasses and type aliases  [Pinboard.Client](https://hackage.haskell.org/package/pinboard/docs/Pinboard-Client.html) 
changelog.md view
@@ -1,3 +1,8 @@+__v0.9.0__++refactored Client.hs to simplify parameters+promote types under .Client subtree to top-level+ __v0.8.5__  replace Pinboard stack with PinboardT transfomer (use mtl style constraints instead of a fixed monad transformer stack)
pinboard.cabal view
@@ -1,5 +1,5 @@ name:                pinboard-version:             0.8.10+version:             0.9.0 synopsis:            Access to the Pinboard API license:             MIT license-file:        LICENSE@@ -18,18 +18,6 @@     library wraps the API exposing functions and data     structures suitable for usage in Haskell programs.     .-    Example:-    .-    > import Pinboard-    > -    > main :: IO ()-    > main = do-    >   let config = fromApiToken "api token"-    >   result <- runPinboard config $ getPostsRecent Nothing Nothing-    >   case result of-    >     Right details -> print details-    >     Left pinboardError -> print pinboardError-    . Extra-Source-Files:         README.md changelog.md library @@ -60,9 +48,9 @@                        Pinboard.ApiRequest                        Pinboard.ApiTypes                         Pinboard.Client-                       Pinboard.Client.Error-                       Pinboard.Client.Types-                       Pinboard.Client.Util+                       Pinboard.Error+                       Pinboard.Types+                       Pinboard.Util   ghc-options:         -Wall -rtsopts  source-repository head
src/Pinboard/Api.hs view
@@ -42,7 +42,7 @@ import Pinboard.Client          (pinboardJson) import Data.Text                (Text) import Data.Time                (UTCTime)-import Pinboard.Client.Types    (MonadPinboard, ResultFormatType (..))+import Pinboard.Types    (MonadPinboard, ResultFormatType (..)) import Pinboard.ApiTypes         import Pinboard.ApiRequest 
src/Pinboard/ApiRequest.hs view
@@ -37,12 +37,12 @@       getNoteRequest,     ) where -import Pinboard.Client.Types    (PinboardRequest (..), Param (..))-import Pinboard.Client.Util     ((</>))+import Pinboard.Types    (PinboardRequest (..), Param (..))+import Pinboard.Util     ((</>)) import Data.Text                (unwords) import Data.Maybe               (catMaybes) import Pinboard.ApiTypes        -import Pinboard.Client.Types    (ResultFormatType (..))+import Pinboard.Types    (ResultFormatType (..))  import Control.Applicative import Prelude hiding (unwords)
src/Pinboard/Client.hs view
@@ -30,8 +30,7 @@       -- * Sending     , sendPinboardRequest       -- *  Manager (http-client)-    , mgrOpenRaw-    , mgrOpen+    , newMgr     , mgrFail      -- * JSON Handling     ,parseJSONResponse@@ -44,13 +43,13 @@     ,createParserErr     ,httpStatusPinboardError      -- * Client Dependencies-    , module Pinboard.Client.Error-    , module Pinboard.Client.Types-    , module Pinboard.Client.Util+    , module Pinboard.Error+    , module Pinboard.Types+    , module Pinboard.Util     ) where  -import Control.Exception          (catch, SomeException, try)+import Control.Exception          (catch, SomeException) import Control.Monad.IO.Class import Control.Monad.Reader import Control.Monad.Except@@ -68,9 +67,9 @@ import           Network.HTTP.Client.TLS  -import Pinboard.Client.Types-import Pinboard.Client.Error-import Pinboard.Client.Util+import Pinboard.Types+import Pinboard.Error+import Pinboard.Util  import qualified Data.ByteString.Lazy        as LBS import qualified Data.Text                   as T@@ -91,16 +90,19 @@     => PinboardConfig     -> PinboardT m a     -> m (Either PinboardError a)-runPinboard config f = mgrOpenRaw >>= go+runPinboard config f = newMgr >>= go     where go mgr = runPinboardT (config, mgr) f   -- | Create a Pinboard value from a PinboardRequest w/ json deserialization-pinboardJson :: (MonadPinboard m, FromJSON a) => PinboardRequest -> m a+pinboardJson +    :: (MonadPinboard m, FromJSON a) +    => PinboardRequest +    -> m a pinboardJson req = do    env <- ask-  res <- sendPinboardRequest env (ensureResultFormatType FormatJson req) parseJSONResponse-  res+  res <- sendPinboardRequest env (ensureResultFormatType FormatJson req) +  parseJSONResponse res  -------------------------------------------------------------------------------- @@ -108,10 +110,9 @@     :: MonadIO m     => PinboardConfig            -> PinboardRequest-    -> (Response LBS.ByteString -> a)-    -> m (Either PinboardError a)-runPinboardSingleRaw config req handler = liftIO $ mgrOpenRaw >>= go-  where go mgr = (Right <$> sendPinboardRequest (config, mgr) req handler)+    -> m (Either PinboardError (Response LBS.ByteString))+runPinboardSingleRaw config req = liftIO $ newMgr >>= go+  where go mgr = (Right <$> sendPinboardRequest (config, mgr) req)                     `catch` mgrFail UnknownErrorType  runPinboardSingleRawBS@@ -120,7 +121,7 @@     -> PinboardRequest     -> m (Either PinboardError LBS.ByteString) runPinboardSingleRawBS config req = do-  res <- runPinboardSingleRaw config req id+  res <- runPinboardSingleRaw config req   return $ do     r <- res     responseBody r <$ checkStatusCodeResponse r@@ -139,15 +140,14 @@       :: MonadIO m       => PinboardEnv       -> PinboardRequest -      -> (Response LBS.ByteString -> a)-      -> m a-sendPinboardRequest (PinboardConfig{..}, man) PinboardRequest{..} handler = do+      -> m (Response LBS.ByteString)+sendPinboardRequest (PinboardConfig{..}, mgr) PinboardRequest{..} = do    let url = T.concat [ requestPath                        , "?"                        , T.decodeUtf8 $ paramsToByteString $ ("auth_token", urlEncode False apiToken) : encodeParams requestParams ]    req <- buildReq $ T.unpack url-   res <- liftIO $ httpLbs req man-   return $ handler res+   res <- liftIO $ httpLbs req mgr+   return res  -------------------------------------------------------------------------------- @@ -155,7 +155,7 @@ buildReq url = do   req <- liftIO $ parseUrl $ "https://api.pinboard.in/v1/" <> url   return $ req -    { requestHeaders = [("User-Agent","pinboard.hs/0.8.10")]+    { requestHeaders = [("User-Agent","pinboard.hs/0.9.0")]     , checkStatus = \_ _ _ -> Nothing     } @@ -212,12 +212,9 @@ --------------------------------------------------------------------------------  -mgrOpenRaw :: MonadIO m => m Manager-mgrOpenRaw = liftIO $ withSocketsDo . newManager +newMgr :: MonadIO m => m Manager+newMgr = liftIO $ withSocketsDo . newManager                  $ managerSetProxy (proxyEnvironment Nothing) tlsManagerSettings--mgrOpen :: MonadIO m => m (Either SomeException Manager)-mgrOpen = liftIO $ try mgrOpenRaw  mgrFail :: MonadIO m => PinboardErrorType -> SomeException -> m (Either PinboardError b) mgrFail e msg = return $ Left $ PinboardError e (toText msg) Nothing Nothing Nothing
− src/Pinboard/Client/Error.hs
@@ -1,56 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--- |--- Module      : Pinboard.Client.Error--- Copyright   : (c) Jon Schoning, 2015--- Maintainer  : jonschoning@gmail.com--- Stability   : experimental--- Portability : POSIX-module Pinboard.Client.Error -    ( defaultPinboardError-    , PinboardErrorHTTPCode (..)-    , PinboardErrorType     (..)-    , PinboardErrorCode     (..)-    , PinboardError         (..)-    ) where--import Data.Text (Text)--import Data.Monoid-import Prelude---------------------------------------------------------------------------------data PinboardErrorHTTPCode = -          BadRequest        -- ^ 400-        | UnAuthorized      -- ^ 401-        | RequestFailed     -- ^ 402-        | Forbidden         -- ^ 403-        | NotFound          -- ^ 404-        | TooManyRequests   -- ^ 429-        | PinboardServerError -- ^ (>=500)-        | UnknownHTTPCode   -- ^ All other codes-          deriving Show---------------------------------------------------------------------------------data PinboardErrorType =-        ConnectionFailure-        | HttpStatusFailure-        | ParseFailure-        | UnknownErrorType -          deriving Show---------------------------------------------------------------------------------data PinboardErrorCode =-        UnknownError -          deriving Show---------------------------------------------------------------------------------data PinboardError = PinboardError {-      errorType  :: PinboardErrorType-    , errorMsg   :: Text-    , errorCode  :: Maybe PinboardErrorCode-    , errorParam :: Maybe Text-    , errorHTTP  :: Maybe PinboardErrorHTTPCode-    } deriving Show--defaultPinboardError :: PinboardError-defaultPinboardError = PinboardError UnknownErrorType mempty Nothing Nothing Nothing 
− src/Pinboard/Client/Types.hs
@@ -1,107 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE OverloadedStrings #-}---- |--- Module      : Pinboard.Client.Types--- Copyright   : (c) Jon Schoning, 2015--- Maintainer  : jonschoning@gmail.com--- Stability   : experimental--- Portability : POSIX-module Pinboard.Client.Types-  ( PinboardEnv-  , PinboardT-  , runPinboardT-  , MonadPinboard-  , PinboardRequest (..)-  , PinboardConfig  (..)-  , ResultFormatType (..)-  , Param (..)-  , ParamsBS-  ) where--import Control.Monad.Reader       (ReaderT)-import Control.Monad.Reader.Class (MonadReader)-import Control.Monad.Trans.Except (ExceptT, runExceptT)-import Control.Monad.Trans.Reader (runReaderT)-import Control.Monad.Error.Class  (MonadError)-import Control.Monad.IO.Class     (MonadIO)--import Data.ByteString            (ByteString)-import Data.Text                  (Text)-import Data.Time.Calendar(Day)-import Data.Time.Clock(UTCTime)-import Network.HTTP.Client        (Manager)--import Pinboard.Client.Error  (PinboardError (..))--import Control.Applicative-import Prelude----------------------------------------------------------------------------------type PinboardEnv = (PinboardConfig, Manager)--type PinboardT m a = ReaderT PinboardEnv (ExceptT PinboardError m) a--runPinboardT -  :: PinboardEnv-  -> PinboardT m a-  -> m (Either PinboardError a)-runPinboardT e f = runExceptT (runReaderT f e)---- |Typeclass alias for the return type of the API functions (keeps the--- signatures less verbose)-type MonadPinboard m =-  ( Functor m-  , Applicative m-  , Monad m-  , MonadIO m-  , MonadIO m-  , MonadReader PinboardEnv m-  , MonadError PinboardError m-  )----------------------------------------------------------------------------------data PinboardRequest = PinboardRequest-    { requestPath    :: Text   -- ^ url path of PinboardRequest-    , requestParams :: [Param] -- ^ Query Parameters of PinboardRequest-    } deriving Show---------------------------------------------------------------------------------data PinboardConfig = PinboardConfig-    { apiToken :: ByteString-    , debug :: Bool-    } deriving Show----------------------------------------------------------------------------------type ParamsBS = [(ByteString, ByteString)]----------------------------------------------------------------------------------data ResultFormatType = FormatJson | FormatXml-      deriving (Show, Eq)--data Param = Format ResultFormatType-           | Tag Text-           | Tags Text-           | Old Text-           | New Text-           | Count Int-           | Start Int-           | Results Int-           | Url Text-           | Date Day-           | DateTime UTCTime-           | FromDateTime UTCTime-           | ToDateTime UTCTime-           | Replace Bool-           | Shared Bool-           | ToRead Bool-           | Description Text-           | Extended Text-           | Meta Int-      deriving (Show, Eq)-
− src/Pinboard/Client/Util.hs
@@ -1,111 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE LambdaCase #-}--- |--- Module      : Pinboard.Client.Util--- Copyright   : (c) Jon Schoning, 2015--- Maintainer  : jonschoning@gmail.com--- Stability   : experimental--- Portability : POSIX-module Pinboard.Client.Util-    ( -      mkConfig-    , paramsToByteString-    , toText-    , toTextLower-    , (</>)-    , paramToName-    , paramToText-    , encodeParams-    , ensureResultFormatType-    ) where--import           Data.String           (IsString)-import           Data.Text             (Text)-import qualified Data.Text             as T-import qualified Data.Text.Encoding    as T-import           Pinboard.Client.Types (PinboardRequest (..), PinboardConfig (..), ResultFormatType (..), Param (..), ParamsBS)-import Network.HTTP.Types(urlEncode)--import Data.Monoid-import Prelude----------------------------------------------------------------------------------mkConfig :: PinboardConfig-mkConfig = PinboardConfig { debug = False, apiToken = mempty }----------------------------------------------------------------------------------- | Conversion from a `Show` constrained type to `Text`-toText-    :: Show a-    => a    -    -> Text -toText = T.pack . show----------------------------------------------------------------------------------- | Conversion from a `Show` constrained type to lowercase `Text`-toTextLower-    :: Show a-    => a    -    -> Text -toTextLower = T.toLower . T.pack . show----------------------------------------------------------------------------------- | Conversion of a key value pair to a query parameterized string-paramsToByteString-    :: (Monoid m, IsString m)-    => [(m, m)]-    -> m-paramsToByteString []           = mempty-paramsToByteString [(x,y)] = x <> "=" <> y-paramsToByteString ((x,y) : xs) =-    mconcat [ x, "=", y, "&" ] <> paramsToByteString xs---- | Retrieve and encode the optional parameters-encodeParams :: [Param] -> ParamsBS-encodeParams xs = do -  x <- xs -  let (k, v) = paramToText x-  return ( T.encodeUtf8 k-         , (urlEncode True . T.encodeUtf8 ) v-         )-ensureResultFormatType :: ResultFormatType -> PinboardRequest -> PinboardRequest-ensureResultFormatType fmt req = -  if hasFormat then req else req { requestParams = Format fmt : params }-  where params = requestParams req-        hasFormat = Format fmt `elem` params---paramToText :: Param -> (Text, Text)-paramToText (Tag a)      = ("tag", a)-paramToText (Tags a)     = ("tags", a)-paramToText (Old a)      = ("old", a)-paramToText (New a)      = ("new", a)-paramToText (Format FormatJson) = ("format", "json")-paramToText (Format FormatXml)  = ("format", "xml")-paramToText (Count a)    = ("count", toText a)-paramToText (Start a)    = ("start", toText a)-paramToText (Results a)  = ("results", toText a)-paramToText (Url a)      = ("url", a)-paramToText (Date a)     = ("dt", toText a)-paramToText (DateTime a) = ("dt", toText a)-paramToText (FromDateTime a) = ("fromdt", toText a)-paramToText (ToDateTime a)   = ("todt", toText a)-paramToText (Replace a)  = ("replace", if a then "yes" else "no")-paramToText (Shared a)   = ("shared", if a then "yes" else "no")-paramToText (ToRead a)   = ("toread", if a then "yes" else "no")-paramToText (Description a) = ("description", a)-paramToText (Extended a) = ("extended", a)-paramToText (Meta a) = ("meta", toText a)--paramToName :: Param -> Text-paramToName = fst . paramToText---------------------------------------------------------------------------------- | Forward slash interspersion on `Monoid` and `IsString`--- constrained types-(</>)-    :: (Monoid m, IsString m)-    => m-    -> m-    -> m-m1 </> m2 = m1 <> "/" <> m2
+ src/Pinboard/Error.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module      : Pinboard.Error+-- Copyright   : (c) Jon Schoning, 2015+-- Maintainer  : jonschoning@gmail.com+-- Stability   : experimental+-- Portability : POSIX+module Pinboard.Error +    ( defaultPinboardError+    , PinboardErrorHTTPCode (..)+    , PinboardErrorType     (..)+    , PinboardErrorCode     (..)+    , PinboardError         (..)+    ) where++import Data.Text (Text)++import Data.Monoid+import Prelude++------------------------------------------------------------------------------+data PinboardErrorHTTPCode = +          BadRequest        -- ^ 400+        | UnAuthorized      -- ^ 401+        | RequestFailed     -- ^ 402+        | Forbidden         -- ^ 403+        | NotFound          -- ^ 404+        | TooManyRequests   -- ^ 429+        | PinboardServerError -- ^ (>=500)+        | UnknownHTTPCode   -- ^ All other codes+          deriving Show++------------------------------------------------------------------------------+data PinboardErrorType =+        ConnectionFailure+        | HttpStatusFailure+        | ParseFailure+        | UnknownErrorType +          deriving Show++------------------------------------------------------------------------------+data PinboardErrorCode =+        UnknownError +          deriving Show++------------------------------------------------------------------------------+data PinboardError = PinboardError {+      errorType  :: PinboardErrorType+    , errorMsg   :: Text+    , errorCode  :: Maybe PinboardErrorCode+    , errorParam :: Maybe Text+    , errorHTTP  :: Maybe PinboardErrorHTTPCode+    } deriving Show++defaultPinboardError :: PinboardError+defaultPinboardError = PinboardError UnknownErrorType mempty Nothing Nothing Nothing 
+ src/Pinboard/Types.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module      : Pinboard.Types+-- Copyright   : (c) Jon Schoning, 2015+-- Maintainer  : jonschoning@gmail.com+-- Stability   : experimental+-- Portability : POSIX+module Pinboard.Types+  ( PinboardEnv+  , PinboardT+  , runPinboardT+  , MonadPinboard+  , PinboardRequest (..)+  , PinboardConfig  (..)+  , ResultFormatType (..)+  , Param (..)+  , ParamsBS+  ) where++import Control.Monad.Reader       (ReaderT)+import Control.Monad.Reader.Class (MonadReader)+import Control.Monad.Trans.Except (ExceptT, runExceptT)+import Control.Monad.Trans.Reader (runReaderT)+import Control.Monad.Error.Class  (MonadError)+import Control.Monad.IO.Class     (MonadIO)++import Data.ByteString            (ByteString)+import Data.Text                  (Text)+import Data.Time.Calendar(Day)+import Data.Time.Clock(UTCTime)+import Network.HTTP.Client        (Manager)++import Pinboard.Error  (PinboardError (..))++import Control.Applicative+import Prelude++------------------------------------------------------------------------------++type PinboardEnv = (PinboardConfig, Manager)++type PinboardT m a = ReaderT PinboardEnv (ExceptT PinboardError m) a++runPinboardT +  :: PinboardEnv+  -> PinboardT m a+  -> m (Either PinboardError a)+runPinboardT e f = runExceptT (runReaderT f e)++-- |Typeclass alias for the return type of the API functions (keeps the+-- signatures less verbose)+type MonadPinboard m =+  ( Functor m+  , Applicative m+  , Monad m+  , MonadIO m+  , MonadReader PinboardEnv m+  , MonadError PinboardError m+  )++------------------------------------------------------------------------------++data PinboardRequest = PinboardRequest+    { requestPath    :: Text   -- ^ url path of PinboardRequest+    , requestParams :: [Param] -- ^ Query Parameters of PinboardRequest+    } deriving Show++------------------------------------------------------------------------------+data PinboardConfig = PinboardConfig+    { apiToken :: ByteString+    , debug :: Bool+    } deriving Show++------------------------------------------------------------------------------++type ParamsBS = [(ByteString, ByteString)]++------------------------------------------------------------------------------++data ResultFormatType = FormatJson | FormatXml+      deriving (Show, Eq)++data Param = Format ResultFormatType+           | Tag Text+           | Tags Text+           | Old Text+           | New Text+           | Count Int+           | Start Int+           | Results Int+           | Url Text+           | Date Day+           | DateTime UTCTime+           | FromDateTime UTCTime+           | ToDateTime UTCTime+           | Replace Bool+           | Shared Bool+           | ToRead Bool+           | Description Text+           | Extended Text+           | Meta Int+      deriving (Show, Eq)+
+ src/Pinboard/Util.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}+-- |+-- Module      : Pinboard.Util+-- Copyright   : (c) Jon Schoning, 2015+-- Maintainer  : jonschoning@gmail.com+-- Stability   : experimental+-- Portability : POSIX+module Pinboard.Util+    ( +      mkConfig+    , paramsToByteString+    , toText+    , toTextLower+    , (</>)+    , paramToName+    , paramToText+    , encodeParams+    , ensureResultFormatType+    ) where++import           Data.String           (IsString)+import           Data.Text             (Text)+import qualified Data.Text             as T+import qualified Data.Text.Encoding    as T+import           Pinboard.Types (PinboardRequest (..), PinboardConfig (..), ResultFormatType (..), Param (..), ParamsBS)+import Network.HTTP.Types(urlEncode)++import Data.Monoid+import Prelude++------------------------------------------------------------------------------++mkConfig :: PinboardConfig+mkConfig = PinboardConfig { debug = False, apiToken = mempty }++------------------------------------------------------------------------------+-- | Conversion from a `Show` constrained type to `Text`+toText+    :: Show a+    => a    +    -> Text +toText = T.pack . show++------------------------------------------------------------------------------+-- | Conversion from a `Show` constrained type to lowercase `Text`+toTextLower+    :: Show a+    => a    +    -> Text +toTextLower = T.toLower . T.pack . show++------------------------------------------------------------------------------+-- | Conversion of a key value pair to a query parameterized string+paramsToByteString+    :: (Monoid m, IsString m)+    => [(m, m)]+    -> m+paramsToByteString []           = mempty+paramsToByteString [(x,y)] = x <> "=" <> y+paramsToByteString ((x,y) : xs) =+    mconcat [ x, "=", y, "&" ] <> paramsToByteString xs++-- | Retrieve and encode the optional parameters+encodeParams :: [Param] -> ParamsBS+encodeParams xs = do +  x <- xs +  let (k, v) = paramToText x+  return ( T.encodeUtf8 k+         , (urlEncode True . T.encodeUtf8 ) v+         )+ensureResultFormatType :: ResultFormatType -> PinboardRequest -> PinboardRequest+ensureResultFormatType fmt req = +  if hasFormat then req else req { requestParams = Format fmt : params }+  where params = requestParams req+        hasFormat = Format fmt `elem` params+++paramToText :: Param -> (Text, Text)+paramToText (Tag a)      = ("tag", a)+paramToText (Tags a)     = ("tags", a)+paramToText (Old a)      = ("old", a)+paramToText (New a)      = ("new", a)+paramToText (Format FormatJson) = ("format", "json")+paramToText (Format FormatXml)  = ("format", "xml")+paramToText (Count a)    = ("count", toText a)+paramToText (Start a)    = ("start", toText a)+paramToText (Results a)  = ("results", toText a)+paramToText (Url a)      = ("url", a)+paramToText (Date a)     = ("dt", toText a)+paramToText (DateTime a) = ("dt", toText a)+paramToText (FromDateTime a) = ("fromdt", toText a)+paramToText (ToDateTime a)   = ("todt", toText a)+paramToText (Replace a)  = ("replace", if a then "yes" else "no")+paramToText (Shared a)   = ("shared", if a then "yes" else "no")+paramToText (ToRead a)   = ("toread", if a then "yes" else "no")+paramToText (Description a) = ("description", a)+paramToText (Extended a) = ("extended", a)+paramToText (Meta a) = ("meta", toText a)++paramToName :: Param -> Text+paramToName = fst . paramToText+------------------------------------------------------------------------------+-- | Forward slash interspersion on `Monoid` and `IsString`+-- constrained types+(</>)+    :: (Monoid m, IsString m)+    => m+    -> m+    -> m+m1 </> m2 = m1 <> "/" <> m2