mirror of
https://github.com/zhigang1992/graphql-engine.git
synced 2026-06-13 01:08:19 +08:00
* basic doc for actions * custom_types, sync and async actions * switch to graphql-parser-hs on github * update docs * metadata import/export * webhook calls are now supported * relationships in sync actions * initialise.sql is now in sync with the migration file * fix metadata tests * allow specifying arguments of actions * fix blacklist check on check_build_worthiness job * track custom_types and actions related tables * handlers are now triggered on async actions * default to pgjson unless a field is involved in relationships, for generating definition list * use 'true' for action filter for non admin role * fix create_action_permission sql query * drop permissions when dropping an action * add a hdb_role view (and relationships) to fetch all roles in the system * rename 'webhook' key in action definition to 'handler' * allow templating actions wehook URLs with env vars * add 'update_action' /v1/query type * allow forwarding client headers by setting `forward_client_headers` in action definition * add 'headers' configuration in action definition * handle webhook error response based on status codes * support array relationships for custom types * implement single row mutation, see https://github.com/hasura/graphql-engine/issues/3731 * single row mutation: rename 'pk_columns' -> 'columns' and no-op refactor * use top level primary key inputs for delete_by_pk & account select permissions for single row mutations * use only REST semantics to resolve the webhook response * use 'pk_columns' instead of 'columns' for update_by_pk input * add python basic tests for single row mutations * add action context (name) in webhook payload * Async action response is accessible for non admin roles only if the request session vars equals to action's * clean nulls, empty arrays for actions, custom types in export metadata * async action mutation returns only the UUID of the action * unit tests for URL template parser * Basic sync actions python tests * fix output in async query & add async tests * add admin secret header in async actions python test * document async action architecture in Resolve/Action.hs file * support actions returning array of objects * tests for list type response actions * update docs with actions and custom types metadata API reference * update actions python tests as per #f8e1330 Co-authored-by: Tirumarai Selvan <tirumarai.selvan@gmail.com> Co-authored-by: Aravind Shankar <face11301@gmail.com> Co-authored-by: Rakesh Emmadi <12475069+rakeshkky@users.noreply.github.com>
95 lines
3.0 KiB
Haskell
95 lines
3.0 KiB
Haskell
-- | A simple URL templating that enables interpolating environment variables
|
|
module Data.URL.Template
|
|
( URLTemplate
|
|
, TemplateItem
|
|
, Variable
|
|
, printURLTemplate
|
|
, parseURLTemplate
|
|
, renderURLTemplate
|
|
, genURLTemplate
|
|
)
|
|
where
|
|
|
|
import Hasura.Prelude
|
|
|
|
import qualified Data.Text as T
|
|
|
|
import Data.Attoparsec.Combinator (lookAhead)
|
|
import Data.Attoparsec.Text
|
|
import Instances.TH.Lift ()
|
|
import Language.Haskell.TH.Syntax (Lift)
|
|
import System.Environment (lookupEnv)
|
|
import Test.QuickCheck
|
|
|
|
newtype Variable = Variable {unVariable :: Text}
|
|
deriving (Show, Eq, Lift, Generic)
|
|
|
|
printVariable :: Variable -> Text
|
|
printVariable var = "{{" <> unVariable var <> "}}"
|
|
|
|
data TemplateItem
|
|
= TIText !Text
|
|
| TIVariable !Variable
|
|
deriving (Show, Eq, Lift, Generic)
|
|
|
|
printTemplateItem :: TemplateItem -> Text
|
|
printTemplateItem = \case
|
|
TIText t -> t
|
|
TIVariable v -> printVariable v
|
|
|
|
-- | A String with environment variables enclosed in '{{' and '}}'
|
|
-- http://{{APP_HOST}}:{{APP_PORT}}/v1/api
|
|
newtype URLTemplate = URLTemplate {unURLTemplate :: [TemplateItem]}
|
|
deriving (Show, Eq, Lift, Generic)
|
|
|
|
printURLTemplate :: URLTemplate -> Text
|
|
printURLTemplate = T.concat . map printTemplateItem . unURLTemplate
|
|
|
|
parseURLTemplate :: Text -> Either String URLTemplate
|
|
parseURLTemplate t = parseOnly parseTemplate t
|
|
where
|
|
parseTemplate :: Parser URLTemplate
|
|
parseTemplate = do
|
|
items <- many parseTemplateItem
|
|
lastItem <- TIText <$> takeText
|
|
pure $ URLTemplate $ items <> [lastItem]
|
|
|
|
parseTemplateItem :: Parser TemplateItem
|
|
parseTemplateItem =
|
|
(TIVariable <$> parseVariable)
|
|
<|> (TIText . T.pack <$> manyTill anyChar (lookAhead $ string "{{"))
|
|
|
|
parseVariable :: Parser Variable
|
|
parseVariable =
|
|
string "{{" *> (Variable . T.pack <$> manyTill anyChar (string "}}"))
|
|
|
|
renderURLTemplate :: MonadIO m => URLTemplate -> m (Either String Text)
|
|
renderURLTemplate template = do
|
|
eitherResults <- mapM renderTemplateItem $ unURLTemplate template
|
|
let errorVariables = lefts eitherResults
|
|
pure $ case errorVariables of
|
|
[] -> Right $ T.concat $ rights eitherResults
|
|
_ -> Left $ T.unpack $ "Value for environment variables not found: "
|
|
<> T.intercalate ", " errorVariables
|
|
where
|
|
renderTemplateItem = \case
|
|
TIText t -> pure $ Right t
|
|
TIVariable (Variable var) -> do
|
|
maybeEnvValue <- liftIO $ lookupEnv $ T.unpack var
|
|
pure $ case maybeEnvValue of
|
|
Nothing -> Left var
|
|
Just value -> Right $ T.pack value
|
|
|
|
-- QuickCheck generators
|
|
instance Arbitrary Variable where
|
|
arbitrary = Variable . T.pack <$> listOf1 (elements $ alphaNumerics <> "-_")
|
|
|
|
instance Arbitrary URLTemplate where
|
|
arbitrary = URLTemplate <$> listOf (oneof [genText, genVariable])
|
|
where
|
|
genText = (TIText . T.pack) <$> listOf1 (elements $ alphaNumerics <> "://")
|
|
genVariable = TIVariable <$> arbitrary
|
|
|
|
genURLTemplate :: Gen URLTemplate
|
|
genURLTemplate = arbitrary
|