diff options
-rw-r--r-- | cli/CHANGELOG.md | 5 | ||||
-rw-r--r-- | cli/LICENSE | 26 | ||||
-rw-r--r-- | cli/app/API/Collection.hs | 33 | ||||
-rw-r--r-- | cli/app/Main.hs | 88 | ||||
-rw-r--r-- | cli/cli.cabal | 24 | ||||
-rw-r--r-- | docs/get-started-cli.md | 22 | ||||
-rw-r--r-- | docs/get-started.md | 4 |
7 files changed, 202 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 diff --git a/docs/get-started-cli.md b/docs/get-started-cli.md new file mode 100644 index 0000000..d78a9a5 --- /dev/null +++ b/docs/get-started-cli.md @@ -0,0 +1,22 @@ +# Get started with the CLI + +## Create a new project + +Create a new folder for your project, `my-project`. Change into it, and set `AMCS_CONTENT` to the folder that should store your content. + +``` +mkdir -p my-project +cd my-project +export ACMS_CONTENT=$PWD/content +``` + +## Create a restaurant collection + +``` +acms collection insert restaurant/1.json <<'EOF' +{ + "name": "Biscotte Restaurant", + "description": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers." +} +EOF +``` diff --git a/docs/get-started.md b/docs/get-started.md new file mode 100644 index 0000000..af435b3 --- /dev/null +++ b/docs/get-started.md @@ -0,0 +1,4 @@ +# Get started + +- [Get started with the CLI](./get-started-cli.md) +- [Get started with the web interface](./get-started-web-interface.md) |