Update stylish haskell config; apply all; add CI config (#1299)

* Update config default; Copy non-defaults

* Update .stylish-haskell config version to match pgrst

* Apply stylish haskell to all files

* CircleCI config

* Remove redundant import.

What is used from Network.HTTP.Types.Headers is also exported by Network.HTTP.Types.

* Grouped imports

* Show un-styled files on CircleCI failure

* Fix styling imports

* Apply adhoc standard correctly
This commit is contained in:
Xavier Francisco
2019-05-23 10:44:34 -05:00
committed by Steve Chávez
parent 16af470a99
commit 28b3d6cafd
43 changed files with 603 additions and 549 deletions
+4 -1
View File
@@ -77,7 +77,7 @@ jobs:
sudo apt-get install -y postgresql-client sudo apt-get install -y postgresql-client
stack setup stack setup
rm -rf $(stack path --dist-dir) $(stack path --local-install-root) rm -rf $(stack path --dist-dir) $(stack path --local-install-root)
stack install hlint packdeps cabal-install stack install hlint packdeps cabal-install stylish-haskell
- run: - run:
name: build src and tests name: build src and tests
command: | command: |
@@ -91,6 +91,9 @@ jobs:
- run: - run:
name: run linter name: run linter
command: git ls-files | grep '\.l\?hs$' | xargs stack exec -- hlint -X QuasiQuotes -X NoPatternSynonyms "$@" command: git ls-files | grep '\.l\?hs$' | xargs stack exec -- hlint -X QuasiQuotes -X NoPatternSynonyms "$@"
- run:
name: run styler
command: git ls-files | grep '\.l\?hs$' | xargs stack exec -- stylish-haskell -i && git diff-index --exit-code HEAD --
- save_cache: - save_cache:
paths: paths:
- "~/.stack" - "~/.stack"
+40 -5
View File
@@ -39,9 +39,9 @@ steps:
# - none: Do not perform any alignment. # - none: Do not perform any alignment.
# #
# Default: global. # Default: global.
align: global align: group
# Folowing options affect only import list alignment. # The following options affect only import list alignment.
# #
# List align has following options: # List align has following options:
# #
@@ -64,6 +64,25 @@ steps:
# Default: after_alias # Default: after_alias
list_align: after_alias list_align: after_alias
# Right-pad the module names to align imports in a group:
#
# - true: a little more readable
#
# > import qualified Data.List as List (concat, foldl, foldr,
# > init, last, length)
# > import qualified Data.List.Extra as List (concat, foldl, foldr,
# > init, last, length)
#
# - false: diff-safe
#
# > import qualified Data.List as List (concat, foldl, foldr, init,
# > last, length)
# > import qualified Data.List.Extra as List (concat, foldl, foldr,
# > init, last, length)
#
# Default: true
pad_module_names: true
# Long list align style takes effect when import is too long. This is # Long list align style takes effect when import is too long. This is
# determined by 'columns' setting. # determined by 'columns' setting.
# #
@@ -75,7 +94,7 @@ steps:
# short enough to fit to single line. Otherwise it'll be multiline. # short enough to fit to single line. Otherwise it'll be multiline.
# #
# - multiline: One line per import list entry. # - multiline: One line per import list entry.
# Type with contructor list acts like single import. # Type with constructor list acts like single import.
# #
# > import qualified Data.Map as M # > import qualified Data.Map as M
# > ( empty # > ( empty
@@ -109,7 +128,7 @@ steps:
# Useful for 'file' and 'group' align settings. # Useful for 'file' and 'group' align settings.
list_padding: 4 list_padding: 4
# Separate lists option affects formating of import list for type # Separate lists option affects formatting of import list for type
# or class. The only difference is single space between type and list # or class. The only difference is single space between type and list
# of constructors, selectors and class functions. # of constructors, selectors and class functions.
# #
@@ -126,6 +145,22 @@ steps:
# Default: true # Default: true
separate_lists: true separate_lists: true
# Space surround option affects formatting of import lists on a single
# line. The only difference is single space after the initial
# parenthesis and a single space before the terminal parenthesis.
#
# - true: There is single space associated with the enclosing
# parenthesis.
#
# > import Data.Foo ( foo )
#
# - false: There is no space associated with the enclosing parenthesis
#
# > import Data.Foo (foo)
#
# Default: false
space_surround: false
# Language pragmas # Language pragmas
- language_pragmas: - language_pragmas:
# We can generate different styles of language pragma lists. # We can generate different styles of language pragma lists.
@@ -142,7 +177,7 @@ steps:
# Align affects alignment of closing pragma brackets. # Align affects alignment of closing pragma brackets.
# #
# - true: Brackets are aligned in same collumn. # - true: Brackets are aligned in same column.
# #
# - false: Brackets are not aligned together. There is only one space # - false: Brackets are not aligned together. There is only one space
# between actual import and closing bracket. # between actual import and closing bracket.
+31 -30
View File
@@ -2,41 +2,42 @@
module Main where module Main where
import PostgREST.App (postgrest)
import PostgREST.Config (AppConfig (..), configPoolTimeout',
prettyVersion, readOptions)
import PostgREST.DbStructure (getDbStructure, getPgVersion)
import PostgREST.Error (errorPayload, checkIsFatal, PgError(PgError))
import PostgREST.OpenAPI (isMalformedProxyUri)
import PostgREST.Types (DbStructure, Schema, PgVersion(..), minimumPgVersion, ConnectionStatus(..))
import Protolude hiding (hPutStrLn, replace)
import Control.AutoUpdate (defaultUpdateSettings,
mkAutoUpdate, updateAction)
import Control.Retry (RetryStatus, capDelay,
exponentialBackoff,
retrying, rsPreviousDelay)
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Base64 as B64
import Data.IORef (IORef, atomicWriteIORef,
newIORef, readIORef)
import Data.String (IsString (..))
import Data.Text (pack, replace, stripPrefix, strip)
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Text.IO (hPutStrLn, readFile)
import Data.Time.Clock (getCurrentTime)
import qualified Hasql.Pool as P import qualified Hasql.Pool as P
import qualified Hasql.Transaction.Sessions as HT import qualified Hasql.Transaction.Sessions as HT
import Network.Wai.Handler.Warp (defaultSettings,
runSettings, setHost, import Control.AutoUpdate (defaultUpdateSettings, mkAutoUpdate,
setPort, setServerName) updateAction)
import System.IO (BufferMode (..), import Control.Retry (RetryStatus, capDelay,
hSetBuffering) exponentialBackoff, retrying,
rsPreviousDelay)
import Data.IORef (IORef, atomicWriteIORef, newIORef,
readIORef)
import Data.String (IsString (..))
import Data.Text (pack, replace, strip, stripPrefix)
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Text.IO (hPutStrLn, readFile)
import Data.Time.Clock (getCurrentTime)
import Network.Wai.Handler.Warp (defaultSettings, runSettings,
setHost, setPort, setServerName)
import System.IO (BufferMode (..), hSetBuffering)
import PostgREST.App (postgrest)
import PostgREST.Config (AppConfig (..), configPoolTimeout',
prettyVersion, readOptions)
import PostgREST.DbStructure (getDbStructure, getPgVersion)
import PostgREST.Error (PgError (PgError), checkIsFatal,
errorPayload)
import PostgREST.OpenAPI (isMalformedProxyUri)
import PostgREST.Types (ConnectionStatus (..), DbStructure,
PgVersion (..), Schema,
minimumPgVersion)
import Protolude hiding (hPutStrLn, replace)
#ifndef mingw32_HOST_OS #ifndef mingw32_HOST_OS
import System.Posix.Signals import System.Posix.Signals
#endif #endif
{-| {-|
@@ -298,6 +299,6 @@ loadDbUriFile conf = extractDbUri mDbUri
extractDbUri dbUri = extractDbUri dbUri =
fmap setDbUri $ fmap setDbUri $
case stripPrefix "@" dbUri of case stripPrefix "@" dbUri of
Nothing -> return dbUri Nothing -> return dbUri
Just filename -> strip <$> readFile (toS filename) Just filename -> strip <$> readFile (toS filename)
setDbUri dbUri = conf {configDatabase = dbUri} setDbUri dbUri = conf {configDatabase = dbUri}
+52 -44
View File
@@ -14,33 +14,41 @@ module PostgREST.ApiRequest (
, userApiRequest , userApiRequest
) where ) where
import Protolude import qualified Data.Aeson as JSON
import qualified Data.Aeson as JSON import qualified Data.ByteString as BS
import Data.Aeson.Types (emptyObject, emptyArray) import qualified Data.ByteString.Internal as BS (c2w)
import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Internal as BS (c2w) import qualified Data.CaseInsensitive as CI
import qualified Data.ByteString.Lazy as BL import qualified Data.Csv as CSV
import qualified Data.Csv as CSV import qualified Data.HashMap.Strict as M
import qualified Data.List as L import qualified Data.List as L
import Data.List (lookup, last, partition) import qualified Data.Set as S
import qualified Data.HashMap.Strict as M import qualified Data.Text as T
import qualified Data.Set as S import qualified Data.Vector as V
import Data.Maybe (fromJust)
import Control.Arrow ((***)) import Control.Arrow ((***))
import qualified Data.Text as T import Data.Aeson.Types (emptyArray, emptyObject)
import qualified Data.Vector as V import Data.List (last, lookup, partition)
import Network.HTTP.Base (urlEncodeVars) import Data.Maybe (fromJust)
import Network.HTTP.Types.Header (hAuthorization, hCookie) import Data.Ranged.Ranges (Range (..), emptyRange,
import Network.HTTP.Types.URI (parseSimpleQuery, parseQueryReplacePlus) rangeIntersection)
import Network.Wai (Request (..)) import Network.HTTP.Base (urlEncodeVars)
import Network.Wai.Parse (parseHttpAccept) import Network.HTTP.Types.Header (hAuthorization, hCookie)
import PostgREST.RangeQuery (NonnegRange, rangeRequested, restrictRange, rangeGeq, allRange, rangeLimit, rangeOffset) import Network.HTTP.Types.URI (parseQueryReplacePlus,
import Data.Ranged.Boundaries parseSimpleQuery)
import PostgREST.Types import Network.Wai (Request (..))
import PostgREST.Error (ApiRequestError(..)) import Network.Wai.Parse (parseHttpAccept)
import Data.Ranged.Ranges (Range(..), rangeIntersection, emptyRange) import Web.Cookie (parseCookiesText)
import qualified Data.CaseInsensitive as CI
import Web.Cookie (parseCookiesText)
import Data.Ranged.Boundaries
import PostgREST.Error (ApiRequestError (..))
import PostgREST.RangeQuery (NonnegRange, allRange, rangeGeq,
rangeLimit, rangeOffset, rangeRequested,
restrictRange)
import PostgREST.Types
import Protolude
type RequestBody = BL.ByteString type RequestBody = BL.ByteString
@@ -68,41 +76,41 @@ data PreferRepresentation = Full | HeadersOnly | None deriving Eq
-} -}
data ApiRequest = ApiRequest { data ApiRequest = ApiRequest {
-- | Similar but not identical to HTTP verb, e.g. Create/Invoke both POST -- | Similar but not identical to HTTP verb, e.g. Create/Invoke both POST
iAction :: Action iAction :: Action
-- | Requested range of rows within response -- | Requested range of rows within response
, iRange :: M.HashMap ByteString NonnegRange , iRange :: M.HashMap ByteString NonnegRange
-- | The target, be it calling a proc or accessing a table -- | The target, be it calling a proc or accessing a table
, iTarget :: Target , iTarget :: Target
-- | Content types the client will accept, [CTAny] if no Accept header -- | Content types the client will accept, [CTAny] if no Accept header
, iAccepts :: [ContentType] , iAccepts :: [ContentType]
-- | Data sent by client and used for mutation actions -- | Data sent by client and used for mutation actions
, iPayload :: Maybe PayloadJSON , iPayload :: Maybe PayloadJSON
-- | If client wants created items echoed back -- | If client wants created items echoed back
, iPreferRepresentation :: PreferRepresentation , iPreferRepresentation :: PreferRepresentation
-- | Pass all parameters as a single json object to a stored procedure -- | Pass all parameters as a single json object to a stored procedure
, iPreferSingleObjectParameter :: Bool , iPreferSingleObjectParameter :: Bool
-- | Whether the client wants a result count (slower) -- | Whether the client wants a result count (slower)
, iPreferCount :: Bool , iPreferCount :: Bool
-- | Whether the client wants to UPSERT or ignore records on PK conflict -- | Whether the client wants to UPSERT or ignore records on PK conflict
, iPreferResolution :: Maybe PreferResolution , iPreferResolution :: Maybe PreferResolution
-- | Filters on the result ("id", "eq.10") -- | Filters on the result ("id", "eq.10")
, iFilters :: [(Text, Text)] , iFilters :: [(Text, Text)]
-- | &and and &or parameters used for complex boolean logic -- | &and and &or parameters used for complex boolean logic
, iLogic :: [(Text, Text)] , iLogic :: [(Text, Text)]
-- | &select parameter used to shape the response -- | &select parameter used to shape the response
, iSelect :: Text , iSelect :: Text
-- | &columns parameter used to shape the payload -- | &columns parameter used to shape the payload
, iColumns :: Maybe Text , iColumns :: Maybe Text
-- | &order parameters for each level -- | &order parameters for each level
, iOrder :: [(Text, Text)] , iOrder :: [(Text, Text)]
-- | Alphabetized (canonical) request query string for response URLs -- | Alphabetized (canonical) request query string for response URLs
, iCanonicalQS :: ByteString , iCanonicalQS :: ByteString
-- | JSON Web Token -- | JSON Web Token
, iJWT :: Text , iJWT :: Text
-- | HTTP request headers -- | HTTP request headers
, iHeaders :: [(Text, Text)] , iHeaders :: [(Text, Text)]
-- | Request Cookies -- | Request Cookies
, iCookies :: [(Text, Text)] , iCookies :: [(Text, Text)]
} }
-- | Examines HTTP request and translates it into user intent. -- | Examines HTTP request and translates it into user intent.
+41 -49
View File
@@ -1,64 +1,56 @@
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NamedFieldPuns #-}
module PostgREST.App ( module PostgREST.App (
postgrest postgrest
) where ) where
import Control.Applicative import qualified Data.ByteString.Char8 as BS
import Data.Aeson as JSON import qualified Data.HashMap.Strict as M
import qualified Data.ByteString.Char8 as BS import qualified Data.Set as S
import Data.Maybe
import Data.IORef (IORef, readIORef)
import Data.Time.Clock (UTCTime)
import qualified Data.Set as S
import qualified Hasql.Pool as P import qualified Hasql.Pool as P
import qualified Hasql.Transaction as H
import qualified Hasql.Transaction as HT import qualified Hasql.Transaction as HT
import qualified Hasql.Transaction.Sessions as HT import qualified Hasql.Transaction.Sessions as HT
import Network.HTTP.Types.Header import Data.Aeson as JSON
import Network.HTTP.Types.Status import Data.Function (id)
import Network.HTTP.Types.URI (renderSimpleQuery) import Data.IORef (IORef, readIORef)
import Network.Wai import Data.Time.Clock (UTCTime)
import Network.Wai.Middleware.RequestLogger (logStdout) import Network.HTTP.Types.URI (renderSimpleQuery)
import Network.Wai.Middleware.RequestLogger (logStdout)
import qualified Hasql.Transaction as H import Control.Applicative
import Data.Maybe
import Network.HTTP.Types.Header
import Network.HTTP.Types.Status
import Network.Wai
import qualified Data.HashMap.Strict as M import PostgREST.ApiRequest (Action (..), ApiRequest (..),
ContentType (..),
import PostgREST.ApiRequest ( ApiRequest(..), ContentType(..) PreferRepresentation (..),
, Action(..), Target(..) Target (..), mutuallyAgreeable,
, PreferRepresentation (..) userApiRequest)
, mutuallyAgreeable import PostgREST.Auth (containsRole, jwtClaims,
, userApiRequest parseSecret)
) import PostgREST.Config (AppConfig (..))
import PostgREST.Auth (jwtClaims, containsRole, parseSecret) import PostgREST.DbRequestBuilder (fieldNames, mutateRequest,
import PostgREST.Config (AppConfig (..)) readRequest)
import PostgREST.DbStructure import PostgREST.DbStructure
import PostgREST.DbRequestBuilder( readRequest import PostgREST.Error (PgError (..), SimpleError (..),
, mutateRequest errorResponseFor)
, fieldNames import PostgREST.Middleware
) import PostgREST.OpenAPI
import PostgREST.Error ( SimpleError(..), PgError(..) import PostgREST.Parsers (pRequestColumns)
, errorResponseFor import PostgREST.QueryBuilder (ResultsWithCount, callProc,
) createReadStatement,
import PostgREST.RangeQuery (allRange, rangeOffset) createWriteStatement,
import PostgREST.Middleware requestToCountQuery,
import PostgREST.QueryBuilder ( callProc requestToQuery)
, requestToQuery import PostgREST.RangeQuery (allRange, rangeOffset)
, requestToCountQuery import PostgREST.Types
, createReadStatement import Protolude hiding (Proxy, intercalate)
, createWriteStatement
, ResultsWithCount
)
import PostgREST.Parsers (pRequestColumns)
import PostgREST.Types
import PostgREST.OpenAPI
import Data.Function (id)
import Protolude hiding (intercalate, Proxy)
postgrest :: AppConfig -> IORef (Maybe DbStructure) -> P.Pool -> IO UTCTime -> IO () -> Application postgrest :: AppConfig -> IORef (Maybe DbStructure) -> P.Pool -> IO UTCTime -> IO () -> Application
postgrest conf refDbStructure pool getTime worker = postgrest conf refDbStructure pool getTime worker =
@@ -211,7 +203,7 @@ app dbStructure proc cols conf apiRequest =
Right (sq, mq) -> do Right (sq, mq) -> do
let isSingle = case pjType of let isSingle = case pjType of
PJArray len -> len == 1 PJArray len -> len == 1
PJObject -> True PJObject -> True
colNames = colName <$> tableCols dbStructure tSchema tName colNames = colName <$> tableCols dbStructure tSchema tName
if topLevelRange /= allRange if topLevelRange /= allRange
then return . errorResponseFor $ PutRangeNotAllowedError then return . errorResponseFor $ PutRangeNotAllowedError
+13 -11
View File
@@ -1,5 +1,5 @@
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-| {-|
Module : PostgREST.Auth Module : PostgREST.Auth
Description : PostgREST authorization functions. Description : PostgREST authorization functions.
@@ -19,17 +19,19 @@ module PostgREST.Auth (
, parseSecret , parseSecret
) where ) where
import Control.Lens.Operators import qualified Crypto.JOSE.Types as JOSE.Types
import Control.Lens (set) import qualified Data.Aeson as JSON
import qualified Data.Aeson as JSON import qualified Data.HashMap.Strict as M
import qualified Data.HashMap.Strict as M import Data.Vector as V
import Data.Time.Clock (UTCTime)
import Data.Vector as V
import PostgREST.Types
import Protolude
import qualified Crypto.JOSE.Types as JOSE.Types import Control.Lens (set)
import Crypto.JWT import Data.Time.Clock (UTCTime)
import Control.Lens.Operators
import Crypto.JWT
import PostgREST.Types
import Protolude
{-| {-|
Possible situations encountered with client JWTs Possible situations encountered with client JWTs
+36 -33
View File
@@ -12,7 +12,8 @@ turned in configurable behaviour if needed.
Other hardcoded options such as the minimum version number also belong here. Other hardcoded options such as the minimum version number also belong here.
-} -}
{-# LANGUAGE LambdaCase, TemplateHaskell #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-}
module PostgREST.Config ( prettyVersion module PostgREST.Config ( prettyVersion
@@ -24,43 +25,45 @@ module PostgREST.Config ( prettyVersion
) )
where where
import Control.Applicative
import Control.Monad (fail)
import Control.Lens (preview)
import Crypto.JWT (StringOrURI,
stringOrUri)
import qualified Data.ByteString as B import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Char8 as BS
import qualified Data.CaseInsensitive as CI import qualified Data.CaseInsensitive as CI
import qualified Data.Configurator as C import qualified Data.Configurator as C
import qualified Data.Configurator.Parser as C import qualified Data.Configurator.Parser as C
import Data.Configurator.Types as C import Data.Configurator.Types as C
import Data.List (lookup)
import Data.Monoid
import Data.Scientific (floatingOrInteger)
import Data.String (String)
import Data.Text (dropWhileEnd, dropEnd,
intercalate, lines,
strip, take, splitOn)
import Data.Text.Encoding (encodeUtf8)
import Data.Text.IO (hPutStrLn)
import Data.Version (versionBranch)
import Development.GitRev (gitHash)
import Network.Wai
import Network.Wai.Middleware.Cors (CorsResourcePolicy (..))
import Options.Applicative hiding (str)
import Paths_postgrest (version)
import PostgREST.Parsers (pRoleClaimKey)
import PostgREST.Types (JSPath, JSPathExp(..))
import PostgREST.Error (ApiRequestError(..))
import Protolude hiding (hPutStrLn, take,
intercalate, (<>))
import System.IO (hPrint)
import System.IO.Error (IOError)
import Text.Heredoc
import Text.PrettyPrint.ANSI.Leijen hiding ((<$>), (<>))
import qualified Text.PrettyPrint.ANSI.Leijen as L import qualified Text.PrettyPrint.ANSI.Leijen as L
import Control.Lens (preview)
import Control.Monad (fail)
import Crypto.JWT (StringOrURI, stringOrUri)
import Data.List (lookup)
import Data.Scientific (floatingOrInteger)
import Data.String (String)
import Data.Text (dropEnd, dropWhileEnd,
intercalate, lines, splitOn,
strip, take)
import Data.Text.Encoding (encodeUtf8)
import Data.Text.IO (hPutStrLn)
import Data.Version (versionBranch)
import Development.GitRev (gitHash)
import Network.Wai.Middleware.Cors (CorsResourcePolicy (..))
import Paths_postgrest (version)
import System.IO (hPrint)
import System.IO.Error (IOError)
import Control.Applicative
import Data.Monoid
import Network.Wai
import Options.Applicative hiding (str)
import Text.Heredoc
import Text.PrettyPrint.ANSI.Leijen hiding ((<$>), (<>))
import PostgREST.Error (ApiRequestError (..))
import PostgREST.Parsers (pRoleClaimKey)
import PostgREST.Types (JSPath, JSPathExp (..))
import Protolude hiding (hPutStrLn, intercalate, take, (<>))
-- | Config file settings for the server -- | Config file settings for the server
data AppConfig = AppConfig { data AppConfig = AppConfig {
configDatabase :: Text configDatabase :: Text
@@ -171,7 +174,7 @@ readOptions = do
coerceText :: Value -> Text coerceText :: Value -> Text
coerceText (String s) = s coerceText (String s) = s
coerceText v = show v coerceText v = show v
coerceInt :: (Read i, Integral i) => Value -> Maybe i coerceInt :: (Read i, Integral i) => Value -> Maybe i
coerceInt (Number x) = rightToMaybe $ floatingOrInteger x coerceInt (Number x) = rightToMaybe $ floatingOrInteger x
@@ -185,11 +188,11 @@ readOptions = do
parseRoleClaimKey :: Value -> Either ApiRequestError JSPath parseRoleClaimKey :: Value -> Either ApiRequestError JSPath
parseRoleClaimKey (String s) = pRoleClaimKey s parseRoleClaimKey (String s) = pRoleClaimKey s
parseRoleClaimKey v = pRoleClaimKey $ show v parseRoleClaimKey v = pRoleClaimKey $ show v
splitExtraSearchPath :: Value -> [Text] splitExtraSearchPath :: Value -> [Text]
splitExtraSearchPath (String s) = strip <$> splitOn "," s splitExtraSearchPath (String s) = strip <$> splitOn "," s
splitExtraSearchPath _ = [] splitExtraSearchPath _ = []
opts = info (helper <*> pathParser) $ opts = info (helper <*> pathParser) $
fullDesc fullDesc
+32 -35
View File
@@ -6,11 +6,11 @@ This module is in charge of building an intermediate representation(ReadRequest,
A query tree is built in case of resource embedding. By inferring the relationship between tables, join conditions are added for every embedded resource. A query tree is built in case of resource embedding. By inferring the relationship between tables, join conditions are added for every embedded resource.
-} -}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE DuplicateRecordFields#-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
module PostgREST.DbRequestBuilder ( module PostgREST.DbRequestBuilder (
readRequest readRequest
@@ -18,36 +18,33 @@ module PostgREST.DbRequestBuilder (
, fieldNames , fieldNames
) where ) where
import Control.Applicative import qualified Data.ByteString.Char8 as BS
import Control.Arrow ((***)) import qualified Data.HashMap.Strict as M
import Control.Lens.Getter (view) import qualified Data.Set as S
import Control.Lens.Tuple (_1)
import qualified Data.ByteString.Char8 as BS
import Data.List (delete)
import Data.Maybe (fromJust)
import qualified Data.Set as S
import Data.Text (isInfixOf)
import Data.Tree
import Data.Either.Combinators (mapLeft)
import Network.Wai import Control.Arrow ((***))
import Control.Lens.Getter (view)
import Control.Lens.Tuple (_1)
import Data.Either.Combinators (mapLeft)
import Data.Foldable (foldr1)
import Data.List (delete)
import Data.Maybe (fromJust)
import Data.Text (isInfixOf)
import Text.Regex.TDFA ((=~))
import Unsafe (unsafeHead)
import Data.Foldable (foldr1) import Control.Applicative
import qualified Data.HashMap.Strict as M import Data.Tree
import Network.Wai
import PostgREST.ApiRequest ( ApiRequest(..) import PostgREST.ApiRequest (Action (..), ApiRequest (..),
, PreferRepresentation(..) PreferRepresentation (..),
, Action(..), Target(..) PreferRepresentation (..), Target (..))
, PreferRepresentation (..) import PostgREST.Error (ApiRequestError (..), errorResponseFor)
) import PostgREST.Parsers
import PostgREST.Error (ApiRequestError(..), errorResponseFor) import PostgREST.RangeQuery (NonnegRange, allRange, restrictRange)
import PostgREST.Parsers import PostgREST.Types
import PostgREST.RangeQuery (NonnegRange, restrictRange, allRange) import Protolude hiding (from)
import PostgREST.Types
import Protolude hiding (from)
import Text.Regex.TDFA ((=~))
import Unsafe (unsafeHead)
readRequest :: Maybe Integer -> [Relation] -> Maybe ProcDescription -> ApiRequest -> Either Response ReadRequest readRequest :: Maybe Integer -> [Relation] -> Maybe ProcDescription -> ApiRequest -> Either Response ReadRequest
readRequest maxRows allRels proc apiRequest = readRequest maxRows allRels proc apiRequest =
@@ -65,9 +62,9 @@ readRequest maxRows allRels proc apiRequest =
(TargetProc (QualifiedIdentifier s pName) ) -> Just (s, tName) (TargetProc (QualifiedIdentifier s pName) ) -> Just (s, tName)
where where
tName = case pdReturnType <$> proc of tName = case pdReturnType <$> proc of
Just (SetOf (Composite qi)) -> qiName qi Just (SetOf (Composite qi)) -> qiName qi
Just (Single (Composite qi)) -> qiName qi Just (Single (Composite qi)) -> qiName qi
_ -> pName _ -> pName
_ -> Nothing _ -> Nothing
@@ -93,7 +90,7 @@ readRequest maxRows allRels proc apiRequest =
ActionUpdate -> fakeSourceRelations ++ allRels ActionUpdate -> fakeSourceRelations ++ allRels
ActionDelete -> fakeSourceRelations ++ allRels ActionDelete -> fakeSourceRelations ++ allRels
ActionInvoke _ -> fakeSourceRelations ++ allRels ActionInvoke _ -> fakeSourceRelations ++ allRels
_ -> allRels _ -> allRels
where fakeSourceRelations = mapMaybe (toSourceRelation rootTableName) allRels where fakeSourceRelations = mapMaybe (toSourceRelation rootTableName) allRels
-- in a relation where one of the tables matches "TableName" -- in a relation where one of the tables matches "TableName"
+19 -19
View File
@@ -10,10 +10,10 @@ These queries are executed once at startup or when PostgREST is reloaded.
-} -}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE NamedFieldPuns #-}
module PostgREST.DbStructure ( module PostgREST.DbStructure (
getDbStructure getDbStructure
, accessibleTables , accessibleTables
@@ -22,26 +22,26 @@ module PostgREST.DbStructure (
, getPgVersion , getPgVersion
) where ) where
import qualified Hasql.Decoders as HD import qualified Data.HashMap.Strict as M
import qualified Hasql.Encoders as HE import qualified Data.List as L
import qualified Hasql.Statement as H import qualified Data.Text as T
import qualified Hasql.Decoders as HD
import qualified Hasql.Encoders as HE
import qualified Hasql.Session as H
import qualified Hasql.Statement as H
import qualified Hasql.Transaction as HT
import Control.Applicative import Data.Set as S (fromList)
import qualified Data.HashMap.Strict as M import Data.Text (breakOn, dropAround, split,
import qualified Data.List as L splitOn, strip)
import Data.Set as S (fromList) import GHC.Exts (groupWith)
import Data.Text (split, strip, import Text.InterpolatedString.Perl6 (q, qc)
breakOn, dropAround, import Unsafe (unsafeHead)
splitOn)
import qualified Data.Text as T
import qualified Hasql.Session as H
import qualified Hasql.Transaction as HT
import PostgREST.Types
import Text.InterpolatedString.Perl6 (q, qc)
import GHC.Exts (groupWith) import Control.Applicative
import Protolude
import Unsafe (unsafeHead) import PostgREST.Types
import Protolude
getDbStructure :: Schema -> PgVersion -> HT.Transaction DbStructure getDbStructure :: Schema -> PgVersion -> HT.Transaction DbStructure
getDbStructure schema pgVer = do getDbStructure schema pgVer = do
+10 -7
View File
@@ -15,17 +15,20 @@ module PostgREST.Error (
, checkIsFatal , checkIsFatal
) where ) where
import Protolude
import Data.Aeson ((.=))
import qualified Data.Aeson as JSON import qualified Data.Aeson as JSON
import Data.Text (unwords)
import qualified Hasql.Pool as P import qualified Hasql.Pool as P
import qualified Hasql.Session as H import qualified Hasql.Session as H
import Network.HTTP.Types.Header
import qualified Network.HTTP.Types.Status as HT import qualified Network.HTTP.Types.Status as HT
import Network.Wai (Response, responseLBS)
import PostgREST.Types import Data.Aeson ((.=))
import Text.Read (readMaybe) import Data.Text (unwords)
import Network.Wai (Response, responseLBS)
import Text.Read (readMaybe)
import Network.HTTP.Types.Header
import PostgREST.Types
import Protolude
class (JSON.ToJSON a) => PgrstError a where class (JSON.ToJSON a) => PgrstError a where
+17 -15
View File
@@ -3,28 +3,30 @@ Module : PostgREST.Middleware
Description : Sets the PostgreSQL GUCs, role, search_path and pre-request function. Validates JWT. Description : Sets the PostgreSQL GUCs, role, search_path and pre-request function. Validates JWT.
-} -}
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
module PostgREST.Middleware where module PostgREST.Middleware where
import Crypto.JWT import qualified Data.Aeson as JSON
import qualified Data.Aeson as JSON import qualified Data.HashMap.Strict as M
import qualified Data.HashMap.Strict as M import qualified Hasql.Transaction as H
import qualified Hasql.Transaction as H
import Network.Wai (Application, Response) import Network.Wai (Application, Response)
import Network.Wai.Middleware.Cors (cors) import Network.Wai.Middleware.Cors (cors)
import Network.Wai.Middleware.Gzip (def, gzip) import Network.Wai.Middleware.Gzip (def, gzip)
import Network.Wai.Middleware.Static (only, staticPolicy) import Network.Wai.Middleware.Static (only, staticPolicy)
import PostgREST.ApiRequest (ApiRequest(..)) import Crypto.JWT
import PostgREST.Auth (JWTAttempt(..))
import PostgREST.Config (AppConfig (..), corsPolicy)
import PostgREST.Error (errorResponseFor, SimpleError(JwtTokenMissing, JwtTokenInvalid))
import PostgREST.QueryBuilder (unquoted, pgFmtSetLocal, pgFmtSetLocalSearchPath)
import Protolude import PostgREST.ApiRequest (ApiRequest (..))
import PostgREST.Auth (JWTAttempt (..))
import PostgREST.Config (AppConfig (..), corsPolicy)
import PostgREST.Error (SimpleError (JwtTokenInvalid, JwtTokenMissing),
errorResponseFor)
import PostgREST.QueryBuilder (pgFmtSetLocal, pgFmtSetLocalSearchPath,
unquoted)
import Protolude
runWithClaims :: AppConfig -> JWTAttempt -> runWithClaims :: AppConfig -> JWTAttempt ->
(ApiRequest -> H.Transaction Response) -> (ApiRequest -> H.Transaction Response) ->
+27 -23
View File
@@ -10,25 +10,29 @@ module PostgREST.OpenAPI (
, pickProxy , pickProxy
) where ) where
import Control.Arrow ((&&&)) import qualified Data.Set as Set
import Control.Lens
import Data.Aeson (decode, encode)
import Data.HashMap.Strict.InsOrd (InsOrdHashMap, fromList)
import Data.Maybe (fromJust)
import qualified Data.Set as Set
import Data.String (IsString (..))
import Data.Text (unpack, pack, init, tail, toLower, intercalate, append, dropWhile, breakOn)
import Network.URI (parseURI, isAbsoluteURI,
URI (..), URIAuth (..))
import Protolude hiding ((&), Proxy, get, intercalate, dropWhile) import Control.Arrow ((&&&))
import Data.Aeson (decode, encode)
import Data.HashMap.Strict.InsOrd (InsOrdHashMap, fromList)
import Data.Maybe (fromJust)
import Data.String (IsString (..))
import Data.Text (append, breakOn, dropWhile, init,
intercalate, pack, tail, toLower,
unpack)
import Network.URI (URI (..), URIAuth (..),
isAbsoluteURI, parseURI)
import Data.Swagger import Control.Lens
import Data.Swagger
import PostgREST.ApiRequest (ContentType(..)) import PostgREST.ApiRequest (ContentType (..))
import PostgREST.Config (prettyVersion, docsVersion) import PostgREST.Config (docsVersion, prettyVersion)
import PostgREST.Types (Table(..), Column(..), PgArg(..), ForeignKey(..), import PostgREST.Types (Column (..), ForeignKey (..), PgArg (..),
PrimaryKey(..), Proxy(..), ProcDescription(..), toMime) PrimaryKey (..), ProcDescription (..),
Proxy (..), Table (..), toMime)
import Protolude hiding (Proxy, dropWhile, get,
intercalate, (&))
makeMimeList :: [ContentType] -> MimeList makeMimeList :: [ContentType] -> MimeList
makeMimeList cs = MimeList $ map (fromString . toS . toMime) cs makeMimeList cs = MimeList $ map (fromString . toS . toMime) cs
@@ -329,7 +333,7 @@ pickProxy proxy
uri = toURI $ fromJust proxy uri = toURI $ fromJust proxy
scheme = init $ toLower $ pack $ uriScheme uri scheme = init $ toLower $ pack $ uriScheme uri
path URI {uriPath = ""} = "/" path URI {uriPath = ""} = "/"
path URI {uriPath = p} = p path URI {uriPath = p} = p
path' = pack $ path uri path' = pack $ path uri
authority = fromJust $ uriAuthority uri authority = fromJust $ uriAuthority uri
host' = pack $ uriRegName authority host' = pack $ uriRegName authority
@@ -337,9 +341,9 @@ pickProxy proxy
readPort = fromMaybe 80 . readMaybe readPort = fromMaybe 80 . readMaybe
port'' :: Integer port'' :: Integer
port'' = case (port', scheme) of port'' = case (port', scheme) of
("", "http") -> 80 ("", "http") -> 80
("", "https") -> 443 ("", "https") -> 443
_ -> readPort $ unpack $ tail $ pack port' _ -> readPort $ unpack $ tail $ pack port'
isUriValid:: URI -> Bool isUriValid:: URI -> Bool
isUriValid = fAnd [isSchemeValid, isQueryValid, isAuthorityValid] isUriValid = fAnd [isSchemeValid, isQueryValid, isAuthorityValid]
@@ -355,7 +359,7 @@ isSchemeValid URI {uriScheme = s}
isQueryValid :: URI -> Bool isQueryValid :: URI -> Bool
isQueryValid URI {uriQuery = ""} = True isQueryValid URI {uriQuery = ""} = True
isQueryValid _ = False isQueryValid _ = False
isAuthorityValid :: URI -> Bool isAuthorityValid :: URI -> Bool
isAuthorityValid URI {uriAuthority = a} isAuthorityValid URI {uriAuthority = a}
@@ -364,16 +368,16 @@ isAuthorityValid URI {uriAuthority = a}
isUserInfoValid :: URIAuth -> Bool isUserInfoValid :: URIAuth -> Bool
isUserInfoValid URIAuth {uriUserInfo = ""} = True isUserInfoValid URIAuth {uriUserInfo = ""} = True
isUserInfoValid _ = False isUserInfoValid _ = False
isHostValid :: URIAuth -> Bool isHostValid :: URIAuth -> Bool
isHostValid URIAuth {uriRegName = ""} = False isHostValid URIAuth {uriRegName = ""} = False
isHostValid _ = True isHostValid _ = True
isPortValid :: URIAuth -> Bool isPortValid :: URIAuth -> Bool
isPortValid URIAuth {uriPort = ""} = True isPortValid URIAuth {uriPort = ""} = True
isPortValid URIAuth {uriPort = (':':p)} = isPortValid URIAuth {uriPort = (':':p)} =
case readMaybe p of case readMaybe p of
Just i -> i > (0 :: Integer) && i < 65536 Just i -> i > (0 :: Integer) && i < 65536
Nothing -> False Nothing -> False
isPortValid _ = False isPortValid _ = False
+19 -16
View File
@@ -6,22 +6,25 @@ This module is in charge of parsing all the querystring values in an url, e.g. t
-} -}
module PostgREST.Parsers where module PostgREST.Parsers where
import Protolude hiding (try, intercalate, replace, option) import qualified Data.HashMap.Strict as M
import Control.Monad ((>>)) import qualified Data.Set as S
import Data.Foldable (foldl1)
import Data.Functor (($>)) import Control.Monad ((>>))
import qualified Data.HashMap.Strict as M import Data.Either.Combinators (mapLeft)
import Data.Text (intercalate, replace, strip) import Data.Foldable (foldl1)
import Data.List (init, last) import Data.Functor (($>))
import qualified Data.Set as S import Data.List (init, last)
import Data.Tree import Data.Text (intercalate, replace, strip)
import Data.Either.Combinators (mapLeft) import Text.Read (read)
import PostgREST.RangeQuery (NonnegRange)
import PostgREST.Error (ApiRequestError(ParseRequestError)) import Data.Tree
import PostgREST.Types import Text.Parsec.Error
import Text.ParserCombinators.Parsec hiding (many, (<|>)) import Text.ParserCombinators.Parsec hiding (many, (<|>))
import Text.Parsec.Error
import Text.Read (read) import PostgREST.Error (ApiRequestError (ParseRequestError))
import PostgREST.RangeQuery (NonnegRange)
import PostgREST.Types
import Protolude hiding (intercalate, option, replace, try)
pRequestSelect :: Text -> Either ApiRequestError [Tree SelectItem] pRequestSelect :: Text -> Either ApiRequestError [Tree SelectItem]
pRequestSelect selStr = pRequestSelect selStr =
+28 -28
View File
@@ -1,6 +1,6 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
{-| {-|
@@ -27,29 +27,29 @@ module PostgREST.QueryBuilder (
, pgFmtSetLocalSearchPath , pgFmtSetLocalSearchPath
) where ) where
import qualified Hasql.Statement as H import qualified Data.Aeson as JSON
import qualified Hasql.Encoders as HE import qualified Data.ByteString.Char8 as BS
import qualified Hasql.Decoders as HD import qualified Data.HashMap.Strict as HM
import qualified Data.Set as S
import qualified Data.Text as T (map, null, takeWhile)
import qualified Data.Text.Encoding as T
import qualified Hasql.Decoders as HD
import qualified Hasql.Encoders as HE
import qualified Hasql.Statement as H
import qualified Data.Aeson as JSON import Data.Scientific (FPFormat (..), formatScientific,
isInteger)
import Data.Text (intercalate, isInfixOf, replace,
toLower, unwords)
import Data.Tree (Tree (..))
import Text.InterpolatedString.Perl6 (qc)
import PostgREST.RangeQuery (rangeLimit, rangeOffset, allRange) import Data.Maybe
import qualified Data.HashMap.Strict as HM
import Data.Maybe import PostgREST.ApiRequest (PreferRepresentation (..))
import qualified Data.Set as S import PostgREST.RangeQuery (allRange, rangeLimit, rangeOffset)
import Data.Text (intercalate, unwords, replace, isInfixOf, toLower) import PostgREST.Types
import qualified Data.Text as T (map, takeWhile, null) import Protolude hiding (cast, intercalate, replace)
import qualified Data.Text.Encoding as T
import Data.Tree (Tree(..))
import PostgREST.Types
import Text.InterpolatedString.Perl6 (qc)
import qualified Data.ByteString.Char8 as BS
import Data.Scientific ( FPFormat (..)
, formatScientific
, isInteger
)
import Protolude hiding ( intercalate, cast, replace)
import PostgREST.ApiRequest (PreferRepresentation (..))
{-| The generic query result format used by API responses. The location header {-| The generic query result format used by API responses. The location header
is represented as a list of strings containing variable bindings like is represented as a list of strings containing variable bindings like
@@ -409,7 +409,7 @@ emptyOnFalse val cond = if cond then "" else val
pgFmtColumn :: QualifiedIdentifier -> Text -> SqlFragment pgFmtColumn :: QualifiedIdentifier -> Text -> SqlFragment
pgFmtColumn table "*" = fromQi table <> ".*" pgFmtColumn table "*" = fromQi table <> ".*"
pgFmtColumn table c = fromQi table <> "." <> pgFmtIdent c pgFmtColumn table c = fromQi table <> "." <> pgFmtIdent c
pgFmtField :: QualifiedIdentifier -> Field -> SqlFragment pgFmtField :: QualifiedIdentifier -> Field -> SqlFragment
pgFmtField table (c, jp) = pgFmtColumn table c <> pgFmtJsonPath jp pgFmtField table (c, jp) = pgFmtColumn table c <> pgFmtJsonPath jp
@@ -427,10 +427,10 @@ pgFmtOrderTerm qi ot = unwords [
pgFmtFilter :: QualifiedIdentifier -> Filter -> SqlFragment pgFmtFilter :: QualifiedIdentifier -> Filter -> SqlFragment
pgFmtFilter table (Filter fld (OpExpr hasNot oper)) = notOp <> " " <> case oper of pgFmtFilter table (Filter fld (OpExpr hasNot oper)) = notOp <> " " <> case oper of
Op op val -> pgFmtFieldOp op <> " " <> case op of Op op val -> pgFmtFieldOp op <> " " <> case op of
"like" -> unknownLiteral (T.map star val) "like" -> unknownLiteral (T.map star val)
"ilike" -> unknownLiteral (T.map star val) "ilike" -> unknownLiteral (T.map star val)
"is" -> whiteList val "is" -> whiteList val
_ -> unknownLiteral val _ -> unknownLiteral val
In vals -> pgFmtField table fld <> " " <> In vals -> pgFmtField table fld <> " " <>
let emptyValForIn = "= any('{}') " in -- Workaround because for postgresql "col IN ()" is invalid syntax, we instead do "col = any('{}')" let emptyValForIn = "= any('{}') " in -- Workaround because for postgresql "col IN ()" is invalid syntax, we instead do "col = any('{}')"
+9 -11
View File
@@ -13,19 +13,17 @@ module PostgREST.RangeQuery (
, NonnegRange , NonnegRange
) where ) where
import qualified Data.ByteString.Char8 as BS
import Control.Applicative import Data.List (lookup)
import Network.HTTP.Types.Header import Text.Regex.TDFA ((=~))
import qualified Data.ByteString.Char8 as BS import Control.Applicative
import Data.Ranged.Boundaries import Data.Ranged.Boundaries
import Data.Ranged.Ranges import Data.Ranged.Ranges
import Network.HTTP.Types.Header
import Text.Regex.TDFA ((=~)) import Protolude
import Data.List (lookup)
import Protolude
type NonnegRange = Range Integer type NonnegRange = Range Integer
@@ -60,7 +58,7 @@ rangeOffset :: NonnegRange -> Integer
rangeOffset range = rangeOffset range =
case rangeLower range of case rangeLower range of
BoundaryBelow lower -> lower BoundaryBelow lower -> lower
_ -> panic "range without lower bound" -- should never happen _ -> panic "range without lower bound" -- should never happen
rangeGeq :: Integer -> NonnegRange rangeGeq :: Integer -> NonnegRange
rangeGeq n = rangeGeq n =
+23 -20
View File
@@ -2,20 +2,23 @@
Module : PostgREST.Types Module : PostgREST.Types
Description : PostgREST common types and functions used by the rest of the modules Description : PostgREST common types and functions used by the rest of the modules
-} -}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
module PostgREST.Types where module PostgREST.Types where
import Protolude
import qualified GHC.Show
import qualified Data.Aeson as JSON import qualified Data.Aeson as JSON
import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy as BL
import qualified Data.CaseInsensitive as CI import qualified Data.CaseInsensitive as CI
import qualified Data.HashMap.Strict as M import qualified Data.HashMap.Strict as M
import qualified Data.Set as S import qualified Data.Set as S
import Data.Tree import qualified GHC.Show
import PostgREST.RangeQuery (NonnegRange)
import Network.HTTP.Types.Header (hContentType, Header) import Network.HTTP.Types.Header (Header, hContentType)
import Data.Tree
import PostgREST.RangeQuery (NonnegRange)
import Protolude
-- | Enumeration of currently supported response content types -- | Enumeration of currently supported response content types
data ContentType = CTApplicationJSON | CTTextCSV | CTOpenAPI data ContentType = CTApplicationJSON | CTTextCSV | CTOpenAPI
@@ -224,10 +227,10 @@ data PayloadJSON =
data PJType = PJArray { pjaLength :: Int } | PJObject deriving (Show, Eq) data PJType = PJArray { pjaLength :: Int } | PJObject deriving (Show, Eq)
data Proxy = Proxy { data Proxy = Proxy {
proxyScheme :: Text proxyScheme :: Text
, proxyHost :: Text , proxyHost :: Text
, proxyPort :: Integer , proxyPort :: Integer
, proxyPath :: Text , proxyPath :: Text
} deriving (Show, Eq) } deriving (Show, Eq)
type Operator = Text type Operator = Text
@@ -272,8 +275,8 @@ type ListVal = [Text]
data LogicOperator = And | Or deriving Eq data LogicOperator = And | Or deriving Eq
instance Show LogicOperator where instance Show LogicOperator where
show And = "AND" show And = "AND"
show Or = "OR" show Or = "OR"
{-| {-|
Boolean logic expression tree e.g. "and(name.eq.N,or(id.eq.1,id.eq.2))" is: Boolean logic expression tree e.g. "and(name.eq.N,or(id.eq.1,id.eq.2))" is:
@@ -353,15 +356,15 @@ data MutateQuery =
, returning :: [FieldName] , returning :: [FieldName]
}| }|
Update { Update {
in_ :: TableName in_ :: TableName
, updCols :: S.Set FieldName , updCols :: S.Set FieldName
, where_ :: [LogicTree] , where_ :: [LogicTree]
, returning :: [FieldName] , returning :: [FieldName]
}| }|
Delete { Delete {
in_ :: TableName in_ :: TableName
, where_ :: [LogicTree] , where_ :: [LogicTree]
, returning :: [FieldName] , returning :: [FieldName]
} deriving (Show, Eq) } deriving (Show, Eq)
data DbRequest = DbRead ReadRequest | DbMutate MutateRequest data DbRequest = DbRead ReadRequest | DbMutate MutateRequest
+6 -5
View File
@@ -1,13 +1,14 @@
module Feature.AndOrParamsSpec where module Feature.AndOrParamsSpec where
import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import Network.Wai (Application) import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Protolude hiding (get)
import SpecHelper import SpecHelper
import Protolude hiding (get)
spec :: SpecWith Application spec :: SpecWith Application
+5 -5
View File
@@ -1,14 +1,14 @@
module Feature.AsymmetricJwtSpec where module Feature.AsymmetricJwtSpec where
-- {{{ Imports -- {{{ Imports
import Test.Hspec
import Test.Hspec.Wai
import Network.HTTP.Types
import SpecHelper
import Network.Wai (Application) import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec
import Test.Hspec.Wai
import Protolude import Protolude
import SpecHelper
-- }}} -- }}}
spec :: SpecWith Application spec :: SpecWith Application
+6 -6
View File
@@ -1,14 +1,14 @@
module Feature.AudienceJwtSecretSpec where module Feature.AudienceJwtSecretSpec where
-- {{{ Imports -- {{{ Imports
import Test.Hspec
import Test.Hspec.Wai
import Network.HTTP.Types
import SpecHelper
import Network.Wai (Application) import Network.Wai (Application)
import Protolude hiding (get) import Network.HTTP.Types
import Test.Hspec
import Test.Hspec.Wai
import Protolude hiding (get)
import SpecHelper
-- }}} -- }}}
spec :: SpecWith Application spec :: SpecWith Application
+6 -7
View File
@@ -1,17 +1,16 @@
module Feature.AuthSpec where module Feature.AuthSpec where
import Text.Heredoc import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types import Text.Heredoc
import SpecHelper
import Network.Wai (Application)
import Protolude hiding (get)
import PostgREST.Types (PgVersion, pgVersion112) import PostgREST.Types (PgVersion, pgVersion112)
import Protolude hiding (get)
import SpecHelper
spec :: PgVersion -> SpecWith Application spec :: PgVersion -> SpecWith Application
spec actualPgVersion = describe "authorization" $ do spec actualPgVersion = describe "authorization" $ do
+5 -5
View File
@@ -1,14 +1,14 @@
module Feature.BinaryJwtSecretSpec where module Feature.BinaryJwtSecretSpec where
-- {{{ Imports -- {{{ Imports
import Test.Hspec
import Test.Hspec.Wai
import Network.HTTP.Types
import SpecHelper
import Network.Wai (Application) import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec
import Test.Hspec.Wai
import Protolude import Protolude
import SpecHelper
-- }}} -- }}}
spec :: SpecWith Application spec :: SpecWith Application
+10 -9
View File
@@ -1,20 +1,21 @@
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, UndecidableInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
module Feature.ConcurrentSpec where module Feature.ConcurrentSpec where
import Control.Monad (void)
import Control.Monad.Base
import Control.Monad.Trans.Control
import Control.Concurrent.Async (mapConcurrently) import Control.Concurrent.Async (mapConcurrently)
import Control.Monad (void)
import Network.Wai (Application)
import Control.Monad.Base
import Control.Monad.Trans.Control
import Network.Wai.Test (Session)
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai.Internal
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.Internal
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.Wai.Test (Session)
import Network.Wai (Application)
import Protolude hiding (get) import Protolude hiding (get)
+5 -5
View File
@@ -1,17 +1,17 @@
module Feature.CorsSpec where module Feature.CorsSpec where
-- {{{ Imports -- {{{ Imports
import Test.Hspec
import Test.Hspec.Wai
import Network.Wai.Test (SResponse(simpleHeaders, simpleBody))
import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy as BL
import SpecHelper import Network.Wai (Application)
import Network.Wai.Test (SResponse (simpleBody, simpleHeaders))
import Network.HTTP.Types import Network.HTTP.Types
import Network.Wai (Application) import Test.Hspec
import Test.Hspec.Wai
import Protolude import Protolude
import SpecHelper
-- }}} -- }}}
spec :: SpecWith Application spec :: SpecWith Application
+3 -3
View File
@@ -1,12 +1,12 @@
module Feature.DeleteSpec where module Feature.DeleteSpec where
import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Text.Heredoc import Text.Heredoc
import Network.HTTP.Types
import Network.Wai (Application)
import Protolude hiding (get) import Protolude hiding (get)
spec :: SpecWith Application spec :: SpecWith Application
+3 -4
View File
@@ -1,14 +1,13 @@
module Feature.ExtraSearchPathSpec where module Feature.ExtraSearchPathSpec where
import Network.HTTP.Types
import Network.Wai (Application)
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import SpecHelper
import Network.Wai (Application)
import Protolude import Protolude
import SpecHelper
spec :: SpecWith Application spec :: SpecWith Application
spec = describe "extra search path" $ do spec = describe "extra search path" $ do
+14 -17
View File
@@ -1,27 +1,24 @@
module Feature.InsertSpec where module Feature.InsertSpec where
import Test.Hspec hiding (pendingWith) import qualified Data.Aeson as JSON
import Control.Monad (replicateM_, void)
import Data.List (lookup)
import Data.Maybe (fromJust)
import Network.Wai (Application)
import Network.Wai.Test (SResponse (simpleBody, simpleHeaders, simpleStatus))
import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai.Matcher (bodyEquals)
import TestTypes (CompoundPK (..), IncPK (..))
import Network.HTTP.Types
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Test.Hspec.Wai.Matcher (bodyEquals)
import Network.Wai.Test (SResponse(simpleBody,simpleHeaders,simpleStatus))
import SpecHelper
import qualified Data.Aeson as JSON
import Data.List (lookup)
import Data.Maybe (fromJust)
import Text.Heredoc import Text.Heredoc
import Network.HTTP.Types.Header
import Network.HTTP.Types
import Control.Monad (replicateM_, void)
import TestTypes(IncPK(..), CompoundPK(..))
import Network.Wai (Application)
import Protolude hiding (get)
import PostgREST.Types (PgVersion, pgVersion112) import PostgREST.Types (PgVersion, pgVersion112)
import Protolude hiding (get)
import SpecHelper
spec :: PgVersion -> SpecWith Application spec :: PgVersion -> SpecWith Application
spec actualPgVersion = do spec actualPgVersion = do
+5 -6
View File
@@ -1,16 +1,15 @@
module Feature.JsonOperatorSpec where module Feature.JsonOperatorSpec where
import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import SpecHelper
import Network.Wai (Application)
import Protolude hiding (get)
import PostgREST.Types (PgVersion, pgVersion112) import PostgREST.Types (PgVersion, pgVersion112)
import Protolude hiding (get)
import SpecHelper
spec :: PgVersion -> SpecWith Application spec :: PgVersion -> SpecWith Application
spec actualPgVersion = describe "json and jsonb operators" $ do spec actualPgVersion = describe "json and jsonb operators" $ do
+5 -4
View File
@@ -1,15 +1,16 @@
module Feature.NoJwtSpec where module Feature.NoJwtSpec where
-- {{{ Imports -- {{{ Imports
import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import SpecHelper
import Network.Wai (Application)
import Protolude import Protolude
import SpecHelper
-- }}} -- }}}
spec :: SpecWith Application spec :: SpecWith Application
+3 -1
View File
@@ -1,10 +1,12 @@
module Feature.NonexistentSchemaSpec where module Feature.NonexistentSchemaSpec where
import Network.Wai (Application) import Network.Wai (Application)
import Protolude hiding (get)
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Protolude hiding (get)
spec :: SpecWith Application spec :: SpecWith Application
spec = spec =
describe "Non existent api schema" $ do describe "Non existent api schema" $ do
+3 -3
View File
@@ -1,13 +1,13 @@
module Feature.PgVersion95Spec where module Feature.PgVersion95Spec where
import Network.Wai (Application)
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Protolude hiding (get)
import SpecHelper import SpecHelper
import Network.Wai (Application)
import Protolude hiding (get)
spec :: SpecWith Application spec :: SpecWith Application
spec = describe "features supported on PostgreSQL 9.5" $ spec = describe "features supported on PostgreSQL 9.5" $
+3 -3
View File
@@ -1,13 +1,13 @@
module Feature.PgVersion96Spec where module Feature.PgVersion96Spec where
import Network.Wai (Application)
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Protolude hiding (get)
import SpecHelper import SpecHelper
import Network.Wai (Application)
import Protolude hiding (get)
spec :: SpecWith Application spec :: SpecWith Application
spec = spec =
+4 -5
View File
@@ -1,13 +1,12 @@
module Feature.ProxySpec where module Feature.ProxySpec where
import Test.Hspec hiding (pendingWith) import Network.Wai (Application)
import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai import Test.Hspec.Wai
import SpecHelper
import Network.Wai (Application)
import Protolude import Protolude
import SpecHelper
spec :: SpecWith Application spec :: SpecWith Application
spec = spec =
+6 -5
View File
@@ -1,14 +1,15 @@
module Feature.QueryLimitedSpec where module Feature.QueryLimitedSpec where
import Network.Wai (Application)
import Network.Wai.Test (SResponse (simpleHeaders, simpleStatus))
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import Network.Wai.Test (SResponse(simpleHeaders, simpleStatus))
import SpecHelper
import Network.Wai (Application)
import Protolude hiding (get) import Protolude hiding (get)
import SpecHelper
spec :: SpecWith Application spec :: SpecWith Application
spec = spec =
+6 -5
View File
@@ -1,16 +1,17 @@
module Feature.QuerySpec where module Feature.QuerySpec where
import Network.Wai (Application)
import Network.Wai.Test (SResponse (simpleHeaders))
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import Network.Wai.Test (SResponse(simpleHeaders))
import SpecHelper
import Text.Heredoc import Text.Heredoc
import Network.Wai (Application)
import Protolude hiding (get) import Protolude hiding (get)
import SpecHelper
spec :: SpecWith Application spec :: SpecWith Application
spec = do spec = do
+7 -7
View File
@@ -1,17 +1,17 @@
module Feature.RangeSpec where module Feature.RangeSpec where
import qualified Data.ByteString.Lazy as BL
import Network.Wai (Application)
import Network.Wai.Test (SResponse (simpleHeaders, simpleStatus))
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import Network.Wai.Test (SResponse(simpleHeaders,simpleStatus))
import qualified Data.ByteString.Lazy as BL
import Protolude hiding (get)
import SpecHelper import SpecHelper
import Network.Wai (Application)
import Protolude hiding (get)
defaultRange :: BL.ByteString defaultRange :: BL.ByteString
defaultRange = [json| { "min": 0, "max": 15 } |] defaultRange = [json| { "min": 0, "max": 15 } |]
+8 -8
View File
@@ -1,19 +1,19 @@
module Feature.RpcSpec where module Feature.RpcSpec where
import qualified Data.ByteString.Lazy as BL (empty)
import Network.Wai (Application)
import Network.Wai.Test (SResponse (simpleBody, simpleStatus))
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import Network.Wai.Test (SResponse(simpleStatus, simpleBody))
import qualified Data.ByteString.Lazy as BL (empty)
import SpecHelper
import Text.Heredoc import Text.Heredoc
import Network.Wai (Application)
import Protolude hiding (get)
import PostgREST.Types (PgVersion, pgVersion95) import PostgREST.Types (PgVersion, pgVersion95)
import Protolude hiding (get)
import SpecHelper
spec :: PgVersion -> SpecWith Application spec :: PgVersion -> SpecWith Application
spec actualPgVersion = spec actualPgVersion =
+6 -6
View File
@@ -1,16 +1,16 @@
module Feature.SingularSpec where module Feature.SingularSpec where
import Text.Heredoc import Network.Wai (Application)
import Network.Wai.Test (SResponse (..))
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types import Text.Heredoc
import Network.Wai.Test (SResponse(..))
import Network.Wai (Application)
import Protolude hiding (get)
import SpecHelper import SpecHelper
import Protolude hiding (get)
spec :: SpecWith Application spec :: SpecWith Application
+11 -11
View File
@@ -1,22 +1,22 @@
module Feature.StructureSpec where module Feature.StructureSpec where
import Test.Hspec hiding (pendingWith) import Control.Lens ((^?))
import Test.Hspec.Wai
import Network.HTTP.Types
import PostgREST.Config (docsVersion)
import Control.Lens ((^?))
import Data.Aeson.Types (Value (..)) import Data.Aeson.Types (Value (..))
import Network.Wai (Application)
import Network.Wai.Test (SResponse (..))
import Data.Aeson.Lens import Data.Aeson.Lens
import Data.Aeson.QQ import Data.Aeson.QQ
import Network.HTTP.Types
import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai
import PostgREST.Config (docsVersion)
import Protolude hiding (get)
import SpecHelper import SpecHelper
import Network.Wai (Application)
import Network.Wai.Test (SResponse(..))
import Protolude hiding (get)
spec :: SpecWith Application spec :: SpecWith Application
spec = do spec = do
+4 -4
View File
@@ -1,15 +1,15 @@
module Feature.UnicodeSpec where module Feature.UnicodeSpec where
import Control.Monad (void)
import Network.Wai (Application)
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.Wai (Application)
import Control.Monad (void)
import Protolude hiding (get)
import SpecHelper import SpecHelper
import Protolude hiding (get)
spec :: SpecWith Application spec :: SpecWith Application
spec = spec =
describe "Reading and writing to unicode schema and table names" $ describe "Reading and writing to unicode schema and table names" $
+6 -6
View File
@@ -1,16 +1,16 @@
module Feature.UpsertSpec where module Feature.UpsertSpec where
import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec import Test.Hspec
import Test.Hspec.Wai import Test.Hspec.Wai
import Test.Hspec.Wai.JSON import Test.Hspec.Wai.JSON
import Network.HTTP.Types
import SpecHelper
import Network.Wai (Application)
import Protolude hiding (get, put)
import Text.Heredoc import Text.Heredoc
import Protolude hiding (get, put)
import SpecHelper
spec :: SpecWith Application spec :: SpecWith Application
spec = spec =
describe "UPSERT" $ do describe "UPSERT" $ do
+26 -23
View File
@@ -1,23 +1,28 @@
module Main where module Main where
import Test.Hspec import qualified Hasql.Pool as P
import SpecHelper
import qualified Hasql.Pool as P
import qualified Hasql.Transaction.Sessions as HT import qualified Hasql.Transaction.Sessions as HT
import PostgREST.App (postgrest) import Control.AutoUpdate (defaultUpdateSettings, mkAutoUpdate,
import PostgREST.DbStructure (getDbStructure, getPgVersion) updateAction)
import PostgREST.Types (DbStructure(..), pgVersion95, pgVersion96) import Data.Function (id)
import Control.AutoUpdate (defaultUpdateSettings, mkAutoUpdate, updateAction) import Data.Time.Clock (getCurrentTime)
import Data.Function (id)
import Data.IORef
import Data.Time.Clock (getCurrentTime)
import qualified Feature.AuthSpec import Data.IORef
import Test.Hspec
import PostgREST.App (postgrest)
import PostgREST.DbStructure (getDbStructure, getPgVersion)
import PostgREST.Types (DbStructure (..), pgVersion95,
pgVersion96)
import Protolude
import SpecHelper
import qualified Feature.AndOrParamsSpec
import qualified Feature.AsymmetricJwtSpec import qualified Feature.AsymmetricJwtSpec
import qualified Feature.BinaryJwtSecretSpec
import qualified Feature.AudienceJwtSecretSpec import qualified Feature.AudienceJwtSecretSpec
import qualified Feature.AuthSpec
import qualified Feature.BinaryJwtSecretSpec
import qualified Feature.ConcurrentSpec import qualified Feature.ConcurrentSpec
import qualified Feature.CorsSpec import qualified Feature.CorsSpec
import qualified Feature.DeleteSpec import qualified Feature.DeleteSpec
@@ -25,21 +30,19 @@ import qualified Feature.ExtraSearchPathSpec
import qualified Feature.InsertSpec import qualified Feature.InsertSpec
import qualified Feature.JsonOperatorSpec import qualified Feature.JsonOperatorSpec
import qualified Feature.NoJwtSpec import qualified Feature.NoJwtSpec
import qualified Feature.QueryLimitedSpec
import qualified Feature.QuerySpec
import qualified Feature.RangeSpec
import qualified Feature.StructureSpec
import qualified Feature.SingularSpec
import qualified Feature.UnicodeSpec
import qualified Feature.ProxySpec
import qualified Feature.AndOrParamsSpec
import qualified Feature.RpcSpec
import qualified Feature.NonexistentSchemaSpec import qualified Feature.NonexistentSchemaSpec
import qualified Feature.PgVersion95Spec import qualified Feature.PgVersion95Spec
import qualified Feature.PgVersion96Spec import qualified Feature.PgVersion96Spec
import qualified Feature.ProxySpec
import qualified Feature.QueryLimitedSpec
import qualified Feature.QuerySpec
import qualified Feature.RangeSpec
import qualified Feature.RpcSpec
import qualified Feature.SingularSpec
import qualified Feature.StructureSpec
import qualified Feature.UnicodeSpec
import qualified Feature.UpsertSpec import qualified Feature.UpsertSpec
import Protolude
main :: IO () main :: IO ()
main = do main = do
+21 -24
View File
@@ -1,34 +1,31 @@
module SpecHelper where module SpecHelper where
import Control.Monad (void) import qualified Data.ByteString.Base64 as B64 (decodeLenient, encode)
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy as BL
import qualified Data.Map.Strict as M
import qualified Data.Set as S
import qualified JSONSchema.Draft4 as D4
import qualified System.IO.Error as E
import qualified System.IO.Error as E import Control.Monad (void)
import System.Environment (getEnv) import Data.Aeson (Value (..), decode)
import Data.CaseInsensitive (CI (..))
import Data.List (lookup)
import Data.Maybe (fromJust)
import Network.Wai.Test (SResponse (simpleBody, simpleHeaders, simpleStatus))
import System.Environment (getEnv)
import System.Process (readProcess)
import Text.Regex.TDFA ((=~))
import qualified Data.ByteString.Base64 as B64 (encode, decodeLenient)
import Data.CaseInsensitive (CI(..))
import qualified Data.Set as S
import qualified Data.Map.Strict as M
import Data.List (lookup)
import Text.Regex.TDFA ((=~))
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy as BL
import System.Process (readProcess)
import Text.Heredoc
import PostgREST.Config (AppConfig(..))
import PostgREST.Types (JSPathExp(..))
import Test.Hspec
import Test.Hspec.Wai
import Network.HTTP.Types import Network.HTTP.Types
import Network.Wai.Test (SResponse(simpleStatus, simpleHeaders, simpleBody)) import Test.Hspec
import Test.Hspec.Wai
import Data.Maybe (fromJust) import Text.Heredoc
import Data.Aeson (decode, Value(..))
import qualified JSONSchema.Draft4 as D4
import PostgREST.Config (AppConfig (..))
import PostgREST.Types (JSPathExp (..))
import Protolude import Protolude
matchContentTypeJson :: MatchHeader matchContentTypeJson :: MatchHeader
+6 -6
View File
@@ -3,16 +3,16 @@ module TestTypes (
, CompoundPK(..) , CompoundPK(..)
) where ) where
import Data.Aeson ((.:))
import qualified Data.Aeson as JSON import qualified Data.Aeson as JSON
import Data.Aeson ((.:))
import Protolude import Protolude
data IncPK = IncPK { data IncPK = IncPK {
incId :: Int incId :: Int
, incNullableStr :: Maybe Text , incNullableStr :: Maybe Text
, incStr :: Text , incStr :: Text
, incInsert :: Text , incInsert :: Text
} deriving (Eq, Show) } deriving (Eq, Show)
instance JSON.FromJSON IncPK where instance JSON.FromJSON IncPK where
@@ -24,8 +24,8 @@ instance JSON.FromJSON IncPK where
parseJSON _ = mzero parseJSON _ = mzero
data CompoundPK = CompoundPK { data CompoundPK = CompoundPK {
compoundK1 :: Int compoundK1 :: Int
, compoundK2 :: Text , compoundK2 :: Text
, compoundExtra :: Maybe Int , compoundExtra :: Maybe Int
} deriving (Eq, Show) } deriving (Eq, Show)