hasql-mapping (empty) → 0.1
raw patch · 6 files changed
+270/−0 lines, 6 filesdep +aesondep +basedep +bytestring
Dependencies added: aeson, base, bytestring, hasql, iproute, scientific, text, time, uuid
Files
- LICENSE +22/−0
- README.md +8/−0
- hasql-mapping.cabal +64/−0
- src/library/Hasql/Mapping.hs +11/−0
- src/library/Hasql/Mapping/IsScalar.hs +110/−0
- src/library/Hasql/Mapping/IsStatement.hs +55/−0
+ LICENSE view
@@ -0,0 +1,22 @@+Copyright (c) 2026, Nikita Volkov++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,8 @@+# hasql-mapping++[](https://hackage.haskell.org/package/hasql-mapping)+[](https://nikita-volkov.github.io/hasql-mapping/)++SDK for defining mappings between Haskell and PostgreSQL.++The central piece of this library is the `IsStatement` typeclass, which is used for declaring type-safe mappings to particular SQL statements.
+ hasql-mapping.cabal view
@@ -0,0 +1,64 @@+cabal-version: 3.0+name: hasql-mapping+version: 0.1+synopsis: SDK for defining modular mappings to databases on top of Hasql+description:+ SDK for defining mappings to databases using Hasql that promotes modular design.++ It avoids exporting abstractions unrelated to mapping, ensuring more stable versioning.++homepage: https://github.com/nikita-volkov/hasql-mapping+bug-reports: https://github.com/nikita-volkov/hasql-mapping/issues+author: Nikita Volkov <nikita.y.volkov@mail.ru>+maintainer: Nikita Volkov <nikita.y.volkov@mail.ru>+copyright: (c) 2026, Nikita Volkov+license: MIT+license-file: LICENSE+extra-doc-files:+ LICENSE+ README.md++source-repository head+ type: git+ location: https://github.com/nikita-volkov/hasql-mapping++common base+ default-language: Haskell2010+ default-extensions:+ ApplicativeDo+ BlockArguments+ DefaultSignatures+ DeriveFunctor+ DerivingStrategies+ DerivingVia+ DuplicateRecordFields+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GeneralizedNewtypeDeriving+ LambdaCase+ MultiParamTypeClasses+ NoImplicitPrelude+ OverloadedStrings+ ScopedTypeVariables+ TypeApplications+ TypeFamilies++library+ import: base+ hs-source-dirs: src/library+ exposed-modules:+ Hasql.Mapping+ Hasql.Mapping.IsScalar+ Hasql.Mapping.IsStatement++ build-depends:+ aeson >=2.0 && <3,+ base >=4.12 && <5,+ bytestring >=0.10 && <0.13,+ hasql ^>=1.10.1,+ iproute >=1.7 && <2,+ scientific >=0.3 && <0.4,+ text >=1.2 && <3,+ time >=1.9 && <2,+ uuid >=1.3 && <2,
+ src/library/Hasql/Mapping.hs view
@@ -0,0 +1,11 @@+-- | Reexports of classes without methods.+--+-- To access the methods import the class-specific modules preferably qualified.+module Hasql.Mapping+ ( IsScalar,+ IsStatement,+ )+where++import Hasql.Mapping.IsScalar (IsScalar)+import Hasql.Mapping.IsStatement (IsStatement)
+ src/library/Hasql/Mapping/IsScalar.hs view
@@ -0,0 +1,110 @@+module Hasql.Mapping.IsScalar where++import qualified Data.Aeson as Aeson+import Data.ByteString (ByteString)+import Data.Functor.Contravariant ((>$<))+import Data.IP (IPRange)+import Data.Int (Int16, Int32, Int64)+import Data.Scientific (Scientific)+import Data.Text (Text)+import Data.Time (Day, DiffTime, LocalTime, TimeOfDay, TimeZone, UTCTime)+import Data.UUID (UUID)+import Data.Word (Word8)+import qualified Hasql.Decoders as Decoders+import qualified Hasql.Encoders as Encoders+import Prelude++-- | Mapping to a scalar value. Anything but array.+--+-- The current Hasql API doesn't provide a typesafe boundary to enforce the value being scalar,+-- so consider this to be a part of the contract to not define instances for array mappings using this class.+class IsScalar a where+ encoder :: Encoders.Value a+ decoder :: Decoders.Value a++-- Numeric types+instance IsScalar Bool where+ encoder = Encoders.bool+ decoder = Decoders.bool++instance IsScalar Int16 where+ encoder = Encoders.int2+ decoder = Decoders.int2++instance IsScalar Int32 where+ encoder = Encoders.int4+ decoder = Decoders.int4++instance IsScalar Int64 where+ encoder = Encoders.int8+ decoder = Decoders.int8++instance IsScalar Int where+ encoder = fromIntegral >$< Encoders.int8+ decoder = fromIntegral <$> Decoders.int8++instance IsScalar Float where+ encoder = Encoders.float4+ decoder = Decoders.float4++instance IsScalar Double where+ encoder = Encoders.float8+ decoder = Decoders.float8++instance IsScalar Scientific where+ encoder = Encoders.numeric+ decoder = Decoders.numeric++-- Text types+instance IsScalar Text where+ encoder = Encoders.text+ decoder = Decoders.text++-- Binary types+instance IsScalar ByteString where+ encoder = Encoders.bytea+ decoder = Decoders.bytea++-- Date/Time types+instance IsScalar Day where+ encoder = Encoders.date+ decoder = Decoders.date++instance IsScalar LocalTime where+ encoder = Encoders.timestamp+ decoder = Decoders.timestamp++instance IsScalar UTCTime where+ encoder = Encoders.timestamptz+ decoder = Decoders.timestamptz++instance IsScalar TimeOfDay where+ encoder = Encoders.time+ decoder = Decoders.time++instance IsScalar (TimeOfDay, TimeZone) where+ encoder = Encoders.timetz+ decoder = Decoders.timetz++instance IsScalar DiffTime where+ encoder = Encoders.interval+ decoder = Decoders.interval++-- UUID+instance IsScalar UUID where+ encoder = Encoders.uuid+ decoder = Decoders.uuid++-- Network types+instance IsScalar IPRange where+ encoder = Encoders.inet+ decoder = Decoders.inet++instance IsScalar (Word8, Word8, Word8, Word8, Word8, Word8) where+ encoder = Encoders.macaddr+ decoder = Decoders.macaddr++-- JSON types+instance IsScalar Aeson.Value where+ encoder = Encoders.jsonb+ decoder = Decoders.jsonb
+ src/library/Hasql/Mapping/IsStatement.hs view
@@ -0,0 +1,55 @@+module Hasql.Mapping.IsStatement where++import qualified Hasql.Statement as Statement++-- |+-- Evidence that a data-structure models statement parameters determining the statement and its result type.+--+-- Supports a modularisation pattern, where you define everything related to one statement in an isolated module.+-- This pattern leads to high code cohesion and low coupling.+--+-- ==== __Example of such a module__+--+-- > module MusicCatalogueDb.Statements.SelectArtistIdsByName where+-- >+-- > import Data.Functor.Contravariant+-- > import Data.Text (Text)+-- > import Data.UUID (UUID)+-- > import Data.Vector (Vector)+-- > import qualified Hasql.Decoders as Decoders+-- > import qualified Hasql.Encoders as Encoders+-- > import Hasql.Mapping.IsStatement+-- > import Prelude+-- >+-- > data SelectArtistIdsByName = SelectArtistIdsByName+-- > { name :: Text+-- > }+-- >+-- > type SelectArtistIdsByNameResult = Vector SelectArtistIdsByNameResultRow+-- >+-- > data SelectArtistIdsByNameResultRow = SelectArtistIdsByNameResultRow+-- > { id :: UUID+-- > }+-- >+-- > instance IsStatement SelectArtistIdsByName where+-- > type Result SelectArtistIdsByName = SelectArtistIdsByNameResult+-- > statement =+-- > Statement.preparable sql encoder decoder+-- > where+-- > sql =+-- > "select id from artist\n\+-- > \where name = $1\n\+-- > \limit 1"+-- > encoder =+-- > mconcat+-- > [ (\(SelectArtistIdsByName x) -> x)+-- > >$< Encoders.param (Encoders.nonNullable Encoders.text)+-- > ]+-- > decoder =+-- > Decoders.rowVector+-- > ( SelectArtistIdsByNameResultRow+-- > <$> Decoders.column (Decoders.nonNullable Decoders.uuid)+-- > )+class IsStatement a where+ type Result a+ statement :: Statement.Statement a (Result a)