diff --git a/api/sql/dump.sql b/api/sql/dump.sql index e41f568..2f9f3c4 100644 --- a/api/sql/dump.sql +++ b/api/sql/dump.sql @@ -3,4 +3,11 @@ CREATE TABLE IF NOT EXISTS users ( username VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, slug VARCHAR(255) UNIQUE NOT NULL +); + +CREATE TABLE IF NOT EXISTS pipelines ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + type VARCHAR(255) NOT NULL, + params JSONB NOT NULL ); \ No newline at end of file diff --git a/api/src/Api/Pipeline.hs b/api/src/Api/Pipeline.hs index dd0813c..cc74838 100644 --- a/api/src/Api/Pipeline.hs +++ b/api/src/Api/Pipeline.hs @@ -3,6 +3,8 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE BlockArguments #-} module Api.Pipeline where @@ -10,27 +12,47 @@ import Servant (Capture, Get, type (:>), JSON, throwError, err401) import Servant.API.Generic ((:-)) import GHC.Generics (Generic) import Data.Int (Int64) -import Db.Pipeline (Pipeline, pipelineSchema, getPipelineById, PipelineId (PipelineId)) +import Db.Pipeline (Pipeline (Pipeline), pipelineSchema, getPipelineById, PipelineId (PipelineId), insertPipeline) import Data.Functor.Identity (Identity) -import Servant.API (Post, Delete, Put) +import Servant.API (Post, Delete, Put, ReqBody) import App (AppM, State (State, dbPool)) import Servant.Server.Generic (AsServerT) import Hasql.Statement (Statement) import Control.Monad.IO.Class (MonadIO) import Control.Monad.Trans.Reader (ask) +import Data.Aeson ( eitherDecode, defaultOptions, FromJSON, ToJSON ) +import Data.Aeson.TH (deriveJSON) import Api.User (runTransactionWithPool) import Hasql.Transaction (Transaction, statement) -import Rel8 (select, each) +import Rel8 (select, each, insert) +import Core.Reaction (ReactionType, ReactionParams) +import Core.Pipeline (PipelineType, PipelineParams) +import Data.Text (Text) +data PipelineData = PipelineData + { pipelineDataName :: Text + , pipelineDataType :: PipelineType + , pipelineDataParams :: PipelineParams + } + +data ReactionData = ReactionData + { reactionDataType :: ReactionType + , reactionDataParams :: ReactionParams + } + data PostPipelineData = PostPipelineData - { action :: Pipeline Identity - , reactions :: [Reaction] + { action :: PipelineData + , reactions :: [ReactionData] } +$(deriveJSON defaultOptions ''PipelineData) +$(deriveJSON defaultOptions ''ReactionData) +$(deriveJSON defaultOptions ''PostPipelineData) + data PipelineAPI mode = PipelineAPI { get :: mode :- Capture "id" Int64 :> Get '[JSON] [Pipeline Identity] - , post :: mode :- Post '[JSON] (Pipeline Identity) + , post :: mode :- ReqBody '[JSON] PostPipelineData :> Post '[JSON] (Pipeline Identity) , put :: mode :- Capture "id" Int64 :> Put '[JSON] (Pipeline Identity) , del :: mode :- Capture "id" Int64 :> Delete '[JSON] (Pipeline Identity) } deriving stock Generic @@ -46,8 +68,17 @@ getPipelineHandler :: Int64 -> AppM [Pipeline Identity] -- runStatement $ select $ getPipelineById (PipelineId slugId) getPipelineHandler _ = throwError err401 -postPipelineHandler :: AppM (Pipeline Identity) -postPipelineHandler = throwError err401 +createPipeline :: Pipeline Identity -> AppM [PipelineId] +createPipeline pipeline = do + State{dbPool = p} <- ask + runTransactionWithPool p $ statement () (insert $ insertPipeline pipeline) + +postPipelineHandler :: PostPipelineData -> AppM (Pipeline Identity) +postPipelineHandler x = do + actionId <- createPipeline $ Pipeline (PipelineId 1) (pipelineDataName p) (pipelineDataType p) (pipelineDataParams p) + throwError err401 + where + p = action x putPipelineHandler :: Int64 -> AppM (Pipeline Identity) putPipelineHandler pipelineId = throwError err401 diff --git a/api/src/Core/Pipeline.hs b/api/src/Core/Pipeline.hs index f2863cf..e40e10b 100644 --- a/api/src/Core/Pipeline.hs +++ b/api/src/Core/Pipeline.hs @@ -3,6 +3,8 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DuplicateRecordFields #-} +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Use newtype instead of data" #-} module Core.Pipeline where @@ -29,7 +31,6 @@ data TwitterNewFollowerData = TwitterNewFollowerData $(deriveJSON defaultOptions ''TwitterNewFollowerData) - data PipelineParams = TwitterNewPostP TwitterNewPostData | TwitterNewFollowerP TwitterNewFollowerData deriving stock (Generic, Show) diff --git a/api/src/Core/Reaction.hs b/api/src/Core/Reaction.hs index ac294ea..8d364fe 100644 --- a/api/src/Core/Reaction.hs +++ b/api/src/Core/Reaction.hs @@ -2,6 +2,8 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE TemplateHaskell #-} +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Use newtype instead of data" #-} module Core.Reaction where @@ -16,8 +18,6 @@ data ReactionType = TwitterTweet | TwitterFollower deriving stock (Generic, Read, Show) deriving DBType via ReadShow ReactionType deriving (FromJSON, ToJSON) - - data TwitterTweetData = TwitterTweetData { body :: Text } deriving (Eq, Show, Generic) diff --git a/api/src/Db/Pipeline.hs b/api/src/Db/Pipeline.hs index 3852930..5e4b79d 100644 --- a/api/src/Db/Pipeline.hs +++ b/api/src/Db/Pipeline.hs @@ -16,7 +16,7 @@ import Data.Aeson ( eitherDecode, defaultOptions, FromJSON, ToJSON ) import Data.Aeson.TH ( deriveJSON ) import GHC.Generics (Generic) -import Rel8 (DBEq, DBType, Column, Rel8able, ReadShow (ReadShow), JSONBEncoded (JSONBEncoded), Result, TableSchema (TableSchema, name, schema, columns), Name, Query, Expr, where_, (==.), lit, each) +import Rel8 (DBEq, DBType, Column, Rel8able, ReadShow (ReadShow), JSONBEncoded (JSONBEncoded), Result, TableSchema (TableSchema, name, schema, columns), Name, Query, Expr, where_, (==.), lit, each, Insert (Insert, returning), into, rows, onConflict, returning, Returning (Projection), OnConflict (DoNothing), values, unsafeCastExpr, nextval) import Data.Text (Text) import Core.Pipeline @@ -40,7 +40,7 @@ instance FromJSON (Pipeline Identity) pipelineSchema :: TableSchema (Pipeline Name) pipelineSchema = TableSchema - { name = "users" + { name = "pipelines" , schema = Nothing , columns = Pipeline { pipelineId = "id" @@ -58,4 +58,18 @@ getPipelineById :: PipelineId -> Query (Pipeline Expr) getPipelineById uid = do u <- selectAllPipelines where_ $ pipelineId u ==. lit uid - return u \ No newline at end of file + return u + + +insertPipeline :: Pipeline Identity -> Insert [PipelineId] +insertPipeline (Pipeline _ name type' params) = Insert + { into = pipelineSchema + , rows = values [ Pipeline { + pipelineId = unsafeCastExpr $ nextval "pipelines_id_seq", + pipelineName = lit name, + pipelineType = lit type', + pipelineParams = lit params + } ] + , onConflict = DoNothing + , returning = Projection pipelineId + } \ No newline at end of file