notion-client 0.7.0.1 → 0.7.0.2
raw patch · 5 files changed
+96/−2 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +5/−0
- README.md +45/−0
- notion-client.cabal +1/−1
- src/Notion/V1/Properties.hs +6/−1
- tasty/Main.hs +39/−0
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Changelog for notion-client +## 0.7.0.2 (2026-06-27)++### Bug Fixes+* Relation property schemas with `single_property` now serialize the required empty `single_property` object, so creating one-directional and self-referential relation columns no longer fails Notion validation with "is not a valid property schema"+ ## 0.7.0.1 (2026-04-16) ### Bug Fixes
README.md view
@@ -147,6 +147,51 @@ } ``` +## Usage with effectful++Callers that use the [`effectful`](https://hackage.haskell.org/package/effectful)+effect system can opt into an `Eff`-typed surface via the companion+package+[`notion-client-effectful`](./notion-client-effectful/). Every+`Notion.V1.Methods` field is re-exposed as a smart constructor of a+`Notion` effect, and a `runNotion` interpreter dispatches through a+concrete `Methods` value. `NotionError` responses surface via the+`Error NotionError` effect rather than as `IO` exceptions.++```haskell+module Demo where++import Data.Text (Text)+import Data.Text qualified as Text+import Effectful (Eff, runEff, (:>))+import Effectful.Error.Static (Error, runErrorNoCallStack)+import Notion.V1 (getClientEnv, makeMethods)+import Notion.V1.Common (UUID (..))+import Notion.V1.Effectful qualified as NE+import Notion.V1.Error (NotionError)+import System.Environment qualified as Env++demo :: (NE.Notion :> es, Error NotionError :> es) => UUID -> Eff es Text+demo pid = do+ page <- NE.retrievePage pid+ pure (Text.pack (show page))++main :: IO ()+main = do+ token <- Text.pack <$> Env.getEnv "NOTION_TOKEN"+ env <- getClientEnv "https://api.notion.com/v1"+ let methods = makeMethods env token+ result <-+ runEff . runErrorNoCallStack @NotionError . NE.runNotion methods $+ demo (UUID "00000000-0000-0000-0000-000000000000")+ print result+```++See [`notion-client-effectful/README.md`](./notion-client-effectful/README.md)+for the full import pattern (qualifying one of the two `Notion.V1`+modules is required — every smart constructor shares its name with+the matching `Methods` record selector).+ ## API Coverage - **Databases**: Create, retrieve, update, and query databases
notion-client.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.4 name: notion-client-version: 0.7.0.1+version: 0.7.0.2 synopsis: Type-safe Haskell client for the Notion API description: This package provides comprehensive and type-safe bindings
src/Notion/V1/Properties.hs view
@@ -499,7 +499,12 @@ FormulaSchema {..} -> (schemaId, schemaName, "formula", object ["expression" .= formulaExpression]) RelationSchema {..} -> let relObj = case relationType of- SingleProperty -> object ["data_source_id" .= relationDataSourceId, "type" .= ("single_property" :: Text)]+ SingleProperty ->+ object+ [ "data_source_id" .= relationDataSourceId,+ "type" .= ("single_property" :: Text),+ "single_property" .= object []+ ] DualProperty {..} -> object [ "data_source_id" .= relationDataSourceId,
tasty/Main.hs view
@@ -660,6 +660,8 @@ testCase "PropertySchema number round-trip" testPropertySchemaNumberRoundTrip, testCase "PropertySchema formula round-trip" testPropertySchemaFormulaRoundTrip, testCase "PropertySchema relation dual round-trip" testPropertySchemaRelationRoundTrip,+ testCase "PropertySchema relation single shape" testPropertySchemaRelationSingleShape,+ testCase "PropertySchema relation single round-trip" testPropertySchemaRelationSingleRoundTrip, testCase "PropertySchema status round-trip" testPropertySchemaStatusRoundTrip, testCase "NumberFormat round-trip" testNumberFormatRoundTrip, testCase "RollupFunction round-trip" testRollupFunctionRoundTrip,@@ -2009,6 +2011,43 @@ schema = Props.RelationSchema {schemaId = "r1", schemaName = "Tasks", relationDataSourceId = UUID "ds-123", relationType = relType} json = Aeson.toJSON schema case Aeson.fromJSON json of+ Aeson.Success decoded -> assertEqual "round-trip" schema decoded+ Aeson.Error err -> assertFailure $ "Failed to decode: " <> err++testPropertySchemaRelationSingleShape :: Assertion+testPropertySchemaRelationSingleShape = do+ let schema =+ Props.RelationSchema+ { schemaId = "r1",+ schemaName = "Depends On",+ relationDataSourceId = UUID "ds-123",+ relationType = Props.SingleProperty+ }+ json = Aeson.toJSON schema+ expected =+ Aeson.object+ [ "id" Aeson..= ("r1" :: Text.Text),+ "name" Aeson..= ("Depends On" :: Text.Text),+ "type" Aeson..= ("relation" :: Text.Text),+ "relation"+ Aeson..= Aeson.object+ [ "data_source_id" Aeson..= ("ds-123" :: Text.Text),+ "type" Aeson..= ("single_property" :: Text.Text),+ "single_property" Aeson..= Aeson.object []+ ]+ ]+ assertEqual "single-property relation JSON shape" expected json++testPropertySchemaRelationSingleRoundTrip :: Assertion+testPropertySchemaRelationSingleRoundTrip = do+ let schema =+ Props.RelationSchema+ { schemaId = "r1",+ schemaName = "Depends On",+ relationDataSourceId = UUID "ds-123",+ relationType = Props.SingleProperty+ }+ case Aeson.fromJSON (Aeson.toJSON schema) of Aeson.Success decoded -> assertEqual "round-trip" schema decoded Aeson.Error err -> assertFailure $ "Failed to decode: " <> err