aboutsummaryrefslogtreecommitdiffstats
path: root/cli
diff options
context:
space:
mode:
authorLibravatar Alexander Foremny <aforemny@posteo.de>2024-10-11 14:17:33 +0200
committerLibravatar Alexander Foremny <aforemny@posteo.de>2024-10-11 14:17:33 +0200
commit35bf45a81da20d782a8a654703eca14543e25def (patch)
tree920d7d884786b900ba194d1433bc010b94f4e46c /cli
parent939cc3e115f5f7b06b09b46c4519502027e25d0d (diff)
add CLI draft
Diffstat (limited to 'cli')
-rw-r--r--cli/CHANGELOG.md5
-rw-r--r--cli/LICENSE26
-rw-r--r--cli/app/API/Collection.hs33
-rw-r--r--cli/app/Main.hs88
-rw-r--r--cli/cli.cabal24
5 files changed, 176 insertions, 0 deletions
diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md
new file mode 100644
index 0000000..b733b96
--- /dev/null
+++ b/cli/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for cli
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/cli/LICENSE b/cli/LICENSE
new file mode 100644
index 0000000..9128a61
--- /dev/null
+++ b/cli/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2024, Alexander Foremny
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cli/app/API/Collection.hs b/cli/app/API/Collection.hs
new file mode 100644
index 0000000..89a5845
--- /dev/null
+++ b/cli/app/API/Collection.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE ViewPatterns #-}
+
+module API.Collection where
+
+import Data.Aeson qualified as A
+import Data.Aeson.KeyMap qualified as AM
+import Data.Text qualified as T
+import Process.Shell (Quotable (..), sh)
+import Debug.Trace
+
+insert :: T.Text -> T.Text -> A.Object -> IO T.Text
+insert
+ collectionName
+ fileName
+ ( traceShowId -> AM.insert "$fileName" (A.String fileName) -> traceShowId ->
+ A.Object -> traceShowId -> contents
+ ) =
+ {- TODO REST/ CRUD API
+ [sh|
+ curl -fsS http://localhost:8081/collections/#{collectionName}/#{filePath} \
+ --data #{contents}
+ \|]-}
+ [sh|
+ set -efux
+ curl -fsS http://localhost:8081 \
+ --data "INSERT "'#{contents}'" INTO #{collectionName}"
+ |]
+
+-- TODO sh
+instance Quotable A.Value where
+ toString = toString . A.encode
diff --git a/cli/app/Main.hs b/cli/app/Main.hs
new file mode 100644
index 0000000..6006e7c
--- /dev/null
+++ b/cli/app/Main.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE NoFieldSelectors #-}
+
+module Main where
+
+import API.Collection qualified
+import Control.Applicative ((<**>))
+import Data.Aeson qualified as J
+import Data.ByteString.Lazy qualified as LB
+import Data.Text qualified as T
+import Options.Applicative qualified as O
+import Text.ParserCombinators.ReadP qualified as R
+import Text.ParserCombinators.ReadPrec qualified as R
+import Text.Read (Read (..))
+
+data Args = Args
+ { cmd :: Cmd
+ }
+
+args :: O.Parser Args
+args = Args <$> cmd_
+
+data Cmd = Collection CollectionCmd
+
+cmd_ :: O.Parser Cmd
+cmd_ =
+ O.hsubparser . mconcat $
+ [ O.command "collection" . O.info collectionCmd $
+ O.progDesc "Manage content collections"
+ ]
+
+data CollectionCmd = CollectionInsert
+ { filePath :: CollectionPath
+ }
+
+data CollectionPath = CollectionPath
+ { collectionName :: T.Text,
+ fileName :: T.Text
+ }
+
+instance Read CollectionPath where
+ readPrec = R.lift do
+ (T.pack -> collectionName) <- R.munch (/= '/')
+ _ <- R.string "/"
+ (T.pack -> fileName) <- do
+ fileName <- R.munch (liftA2 (&&) (/= '.') (/= '/'))
+ fileExt <- R.string ".json"
+ pure (fileName <> fileExt)
+ pure CollectionPath {..}
+
+instance Show CollectionPath where
+ show (CollectionPath {collectionName, fileName}) =
+ show (collectionName <> "/" <> fileName)
+
+collectionCmd :: O.Parser Cmd
+collectionCmd =
+ fmap Collection . O.hsubparser . mconcat $
+ [ O.command "insert" . O.info collectionInsertCmd $
+ O.progDesc "Insert an entity"
+ ]
+
+collectionInsertCmd :: O.Parser CollectionCmd
+collectionInsertCmd =
+ CollectionInsert
+ <$> collectionPathArg
+
+collectionPathArg :: O.Parser CollectionPath
+collectionPathArg =
+ O.argument O.auto (O.metavar "COLLECTION_PATH")
+
+main :: IO ()
+main = do
+ O.execParser (O.info (args <**> O.helper) O.idm) >>= \case
+ Args
+ { cmd =
+ Collection
+ CollectionInsert
+ { filePath = CollectionPath {collectionName, fileName}
+ }
+ } ->
+ print
+ =<< API.Collection.insert collectionName fileName
+ =<< J.throwDecode
+ =<< LB.getContents
diff --git a/cli/cli.cabal b/cli/cli.cabal
new file mode 100644
index 0000000..5065732
--- /dev/null
+++ b/cli/cli.cabal
@@ -0,0 +1,24 @@
+cabal-version: 3.4
+name: cli
+version: 0.1.0.0
+license: BSD-2-Clause
+license-file: LICENSE
+maintainer: aforemny@posteo.de
+author: Alexander Foremny
+build-type: Simple
+extra-doc-files: CHANGELOG.md
+
+executable cli
+ main-is: Main.hs
+ hs-source-dirs: app
+ other-modules: API.Collection
+ default-language: GHC2021
+ ghc-options: -Wall
+ build-depends:
+ aeson,
+ base,
+ bytestring,
+ filepath,
+ optparse-applicative,
+ sh,
+ text