packages feed

notion-client-0.2.0.0: src/Notion/V1.hs

-- | Notion API v1
--
-- Example usage:
--
-- @
-- module Main where
--
-- import Notion.V1
-- import Notion.V1.Pages
-- import Data.Text qualified as Text
-- import System.Environment qualified as Environment
--
-- main :: IO ()
-- main = do
--     token <- Environment.getEnv "NOTION_TOKEN"
--
--     clientEnv <- getClientEnv "https://api.notion.com/v1"
--
--     let Methods{ retrievePage } = makeMethods clientEnv (Text.pack token)
--
--     page <- retrievePage "page-id-here"
--
--     print page
-- @
module Notion.V1
  ( -- * Methods
    getClientEnv,
    makeMethods,
    Methods (..),

    -- * Servant
    API,
  )
where

import Control.Exception qualified as Exception
import Data.Proxy (Proxy (..))
import Data.Text qualified as Text
import Network.HTTP.Client.TLS qualified as TLS
import Notion.Prelude
import Notion.V1.Blocks (BlockID, BlockObject)
import Notion.V1.Blocks qualified as Blocks
import Notion.V1.Comments (CommentObject)
import Notion.V1.Comments qualified as Comments
import Notion.V1.Common (ParentID)
import Notion.V1.DataSources (DataSourceID, DataSourceObject)
import Notion.V1.DataSources qualified as DataSources
import Notion.V1.Databases (CreateDatabase, DatabaseID, DatabaseObject, QueryDatabase, UpdateDatabase)
import Notion.V1.Databases qualified as Databases
import Notion.V1.ListOf (ListOf (..))
import Notion.V1.Pages (CreatePage, PageID, PageMarkdown, PageObject, UpdatePage)
import Notion.V1.Pages qualified as Pages
import Notion.V1.Search (SearchRequest)
import Notion.V1.Search qualified as Search
import Notion.V1.Users (UserID, UserObject)
import Notion.V1.Users qualified as Users
import Servant.Client (ClientEnv)
import Servant.Client qualified as Client
import Servant.Multipart.Client ()

-- | Convenient utility to get a `ClientEnv` for the most common use case
getClientEnv ::
  -- | Base URL for API
  Text ->
  IO ClientEnv
getClientEnv baseUrlText = do
  baseUrl <- Client.parseBaseUrl (Text.unpack baseUrlText)
  manager <- TLS.newTlsManager
  pure (Client.mkClientEnv manager baseUrl)

-- | Get a record of API methods after providing an API token
makeMethods ::
  ClientEnv ->
  -- | API token
  Text ->
  Methods
makeMethods clientEnv token = Methods {..}
  where
    notionVersion = "2026-03-11" -- Notion API version with markdown content support
    -- If you experience 400 errors, check for updated versions at
    -- https://developers.notion.com/reference/versioning
    ( ( createDatabase
          :<|> retrieveDatabase
          :<|> updateDatabase
          :<|> queryDatabase
        )
        :<|> ( retrieveDataSource
                 :<|> createDataSource
                 :<|> updateDataSource
                 :<|> queryDataSource
               )
        :<|> ( retrievePage
                 :<|> createPage
                 :<|> updatePage
                 :<|> retrievePageMarkdown
               )
        :<|> ( retrieveBlock
                 :<|> updateBlock
                 :<|> retrieveBlockChildren_
                 :<|> appendBlockChildren
                 :<|> deleteBlock
               )
        :<|> ( retrieveUser
                 :<|> listUsers_
                 :<|> retrieveMyUser
               )
        :<|> search_
        :<|> ( createComment
                 :<|> listComments_
               )
      ) = Client.hoistClient @API Proxy run (Client.client @API Proxy) authorization notionVersion

    authorization = "Bearer " <> token

    run :: Client.ClientM a -> IO a
    run clientM = do
      result <- Client.runClientM clientM clientEnv
      case result of
        Left exception -> Exception.throwIO exception
        Right a -> return a

    -- Keep the ListOf structure
    listBlockChildren = retrieveBlockChildren_
    listUsers = listUsers_
    listComments = listComments_
    search = search_

-- | API methods
data Methods = Methods
  { -- \* Databases
    createDatabase :: CreateDatabase -> IO DatabaseObject,
    retrieveDatabase :: DatabaseID -> IO DatabaseObject,
    updateDatabase :: DatabaseID -> UpdateDatabase -> IO DatabaseObject,
    queryDatabase :: DatabaseID -> QueryDatabase -> IO (ListOf PageObject),
    -- \* Data Sources
    retrieveDataSource :: DataSourceID -> IO DataSourceObject,
    createDataSource :: DataSources.CreateDataSource -> IO DataSourceObject,
    updateDataSource :: DataSourceID -> DataSources.UpdateDataSource -> IO DataSourceObject,
    queryDataSource :: DataSourceID -> DataSources.QueryDataSource -> IO (ListOf PageObject),
    -- \* Pages
    createPage :: CreatePage -> IO PageObject,
    retrievePage :: PageID -> IO PageObject,
    updatePage :: PageID -> UpdatePage -> IO PageObject,
    retrievePageMarkdown ::
      PageID ->
      Maybe Bool ->
      -- \^ include_transcript
      IO PageMarkdown,
    -- \* Blocks
    retrieveBlock :: BlockID -> IO BlockObject,
    updateBlock :: BlockID -> Blocks.BlockContent -> IO BlockObject,
    listBlockChildren ::
      ParentID ->
      Maybe Natural ->
      -- \^ page_size
      Maybe Text ->
      -- \^ start_cursor
      IO (ListOf BlockObject),
    appendBlockChildren :: ParentID -> Blocks.AppendBlockChildren -> IO (ListOf BlockObject),
    deleteBlock :: BlockID -> IO BlockObject,
    -- \* Users
    retrieveUser :: UserID -> IO UserObject,
    listUsers ::
      Maybe Natural ->
      -- \^ page_size
      Maybe Text ->
      -- \^ start_cursor
      IO (ListOf UserObject),
    retrieveMyUser :: IO UserObject,
    -- \* Search
    search :: SearchRequest -> IO (ListOf Value),
    -- \* Comments
    createComment :: Comments.CreateComment -> IO CommentObject,
    -- | List comments on a block or page. To list comments on a page, use the page ID
    -- as the block_id parameter (pages are blocks in Notion).
    listComments ::
      Maybe BlockID ->
      -- \^ block_id (use page ID here for page comments)
      Maybe Text ->
      -- \^ start_cursor
      Maybe Natural ->
      -- \^ page_size
      IO (ListOf CommentObject)
  }

-- | Servant API
type API =
  Header' [Required, Strict] "Authorization" Text
    :> Header' [Required, Strict] "Notion-Version" Text
    :> ( Databases.API
           :<|> DataSources.API
           :<|> Pages.API
           :<|> Blocks.API
           :<|> Users.API
           :<|> Search.API
           :<|> Comments.API
       )