diff --git a/.github/workflows/nix.yaml b/.github/workflows/nix.yaml index 5b14487..3ee8525 100644 --- a/.github/workflows/nix.yaml +++ b/.github/workflows/nix.yaml @@ -60,4 +60,4 @@ jobs: # FIXME: While the NPM build is not working, I'll need to manually create # The recycle-ics-ui build first - - run: nix-build -A recycle-client -A recycle-ics + - run: nix-build -A recycle-ics diff --git a/README.md b/README.md index c0733db..7a1e23c 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,7 @@ Prerequisites: ## Usage -The application can be used in 3 ways: an API client for the [RecycleApp.be API](recycleapp.be), an CLI ICS file generator for waste collection, and a server for generating the ICS files. - -### API Client - -See `recycle client --help` +The application can be used in 2 ways: an CLI ICS file generator for waste collection, and a server for generating the ICS files. ### CLI app diff --git a/recycle-ics/api/api.http b/api/recycle-ics.http similarity index 100% rename from recycle-ics/api/api.http rename to api/recycle-ics.http diff --git a/recycle-client/api/api.http b/api/recycle.http similarity index 100% rename from recycle-client/api/api.http rename to api/recycle.http diff --git a/cabal.project b/cabal.project index dba2228..08fc3a7 100644 --- a/cabal.project +++ b/cabal.project @@ -1,3 +1,2 @@ packages: - ./recycle-client ./recycle-ics diff --git a/default.nix b/default.nix index 052acfd..dec4e2f 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,6 @@ let export RECYCLE_ICS_WWW_DIR=${recycle-ics-ui} ''; }] else []) ++ (if release then [{ - packages.recycle-client.components.exes.recycle-client.dontStrip = false; packages.recycle-ics.components.exes.recycle-ics.dontStrip = false; }] else [ ]); @@ -32,6 +31,5 @@ let in { inherit sources nixpkgs hsPkgs recycle-ics-ui; - inherit (hsPkgs.recycle-client.components.exes) recycle-client; inherit (hsPkgs.recycle-ics.components.exes) recycle-ics; } diff --git a/recycle-client/LICENSE b/recycle-client/LICENSE deleted file mode 100644 index 3b3ac2e..0000000 --- a/recycle-client/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright © 2022 Brecht Serckx - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/recycle-client/Setup.hs b/recycle-client/Setup.hs deleted file mode 100644 index 9a994af..0000000 --- a/recycle-client/Setup.hs +++ /dev/null @@ -1,2 +0,0 @@ -import Distribution.Simple -main = defaultMain diff --git a/recycle-client/app/Main.hs b/recycle-client/app/Main.hs deleted file mode 100644 index 72e3e04..0000000 --- a/recycle-client/app/Main.hs +++ /dev/null @@ -1,71 +0,0 @@ -{-# LANGUAGE DataKinds #-} - -module Main - ( main, - ) -where - -import qualified Colog -import Control.Monad.IO.Class (liftIO) -import qualified Data.Aeson as Aeson -import qualified Data.ByteString.Lazy.Char8 as BSL8 -import Data.Foldable (for_) -import Data.IORef (newIORef) -import Data.Time hiding (getZonedTime) -import Network.HTTP.Client.TLS - ( newTlsManagerWith, - tlsManagerSettings, - ) -import Opts -import Recycle.AppM -import Recycle.Class -import Recycle.Types -import Servant.Client - ( BaseUrl (..), - Scheme (..), - mkClientEnv, - ) - -main :: IO () -main = do - Opts {apiClientOpts = ApiClientOpts {..}, ..} <- parseOpts - httpManager <- newTlsManagerWith tlsManagerSettings - let clientEnv = - mkClientEnv httpManager $ BaseUrl Https "api.fostplus.be" 443 "" - logAction = - Colog.cfilter - ((>= verbosity) . Colog.msgSeverity) - Colog.simpleMessageAction - - authResult <- newIORef Nothing - let env = Env {..} - flip runRecycle env $ case cmd of - GetAccessToken -> liftIO . BSL8.putStrLn . Aeson.encode =<< getAuthResult - SearchZipcodes mAccessToken mQuery -> do - for_ mAccessToken setAccessToken - zipcodes <- searchZipcodes mQuery - liftIO . BSL8.putStrLn $ Aeson.encode zipcodes - SearchStreets mAccessToken mZipcode mQuery -> do - for_ mAccessToken setAccessToken - streets <- searchStreets mZipcode mQuery - liftIO . BSL8.putStrLn $ Aeson.encode streets - GetCollections mAccessToken zipcode street houseNumber dateRange -> do - for_ mAccessToken setAccessToken - range <- liftIO $ calculateDateRange dateRange - collections <- getCollections zipcode street houseNumber range - liftIO . BSL8.putStrLn $ Aeson.encode collections - GetFractions mAccessToken zipcode street houseNumber -> do - for_ mAccessToken setAccessToken - fractions <- getFractions zipcode street houseNumber - liftIO . BSL8.putStrLn $ Aeson.encode fractions - -calculateDateRange :: (HasTime m) => DateRange -> m (Range Day) -calculateDateRange = \case - AbsoluteDateRange r -> pure r - RelativeDateRange relRange -> do - today <- localDay . zonedTimeToLocalTime <$> getZonedTime - pure - Range - { from = addDays relRange.from today, - to = addDays relRange.to today - } diff --git a/recycle-client/app/Opts.hs b/recycle-client/app/Opts.hs deleted file mode 100644 index 9789f8c..0000000 --- a/recycle-client/app/Opts.hs +++ /dev/null @@ -1,94 +0,0 @@ -module Opts - ( Opts (..), - parseOpts, - ApiClientOpts (..), - ApiClientCmd (..), - module Recycle.Types.Optparse, - ) -where - -import Colog (Severity (..)) -import Data.Text (Text) -import Numeric.Natural (Natural) -import Options.Applicative -import Recycle.Types -import Recycle.Types.Optparse - -data Opts = Opts - { cmd :: ApiClientCmd, - apiClientOpts :: ApiClientOpts, - verbosity :: Severity - } - -parseOpts :: IO Opts -parseOpts = - let parserInfo = mconcat [fullDesc, progDesc "Client for the RecycleApp.be api"] - in execParser $ (pOpts <**> helper) `info` parserInfo - -pOpts :: Parser Opts -pOpts = do - cmd <- pApiClientCmd - apiClientOpts <- pApiClientOpts - verbosity <- - option - auto - ( short 'v' - <> long "verbosity" - <> help "Log error messages of this severity and higher." - <> metavar "SEVERITY" - <> value Warning - ) - pure Opts {..} - -data ApiClientCmd - = GetAccessToken - | SearchZipcodes (Maybe AccessToken) (Maybe (SearchQuery Natural)) - | SearchStreets (Maybe AccessToken) (Maybe ZipcodeId) (Maybe (SearchQuery Text)) - | GetCollections (Maybe AccessToken) ZipcodeId StreetId HouseNumber DateRange - | GetFractions (Maybe AccessToken) ZipcodeId StreetId HouseNumber - -pApiClientCmd :: Parser ApiClientCmd -pApiClientCmd = - hsubparser $ - mconcat - [ command "get-access-token" $ - pure GetAccessToken - `info` (fullDesc <> progDesc "Get an access token"), - command "search-zipcodes" $ - (SearchZipcodes <$> optional pAccessToken <*> optional pSearchQueryNat) - `info` (fullDesc <> progDesc "Search for zipcodes"), - command "search-streets" $ - ( SearchStreets - <$> optional pAccessToken - <*> optional pZipcodeId - <*> optional pSearchQueryText - ) - `info` (fullDesc <> progDesc "Search for streets"), - command "get-collections" $ - ( GetCollections - <$> optional pAccessToken - <*> pZipcodeId - <*> pStreetId - <*> pHouseNumber - <*> pDateRange - ) - `info` (fullDesc <> progDesc "Get collections"), - command "get-fractions" $ - ( GetFractions - <$> optional pAccessToken - <*> pZipcodeId - <*> pStreetId - <*> pHouseNumber - ) - `info` (fullDesc <> progDesc "Get fractions") - ] - -pAccessToken :: Parser AccessToken -pAccessToken = strOption $ long "access-token" <> help "AccessToken" - -pSearchQueryText :: Parser (SearchQuery Text) -pSearchQueryText = strArgument $ metavar "QUERY" <> help "SearchQuery" - -pSearchQueryNat :: Parser (SearchQuery Natural) -pSearchQueryNat = - argument (SearchQuery <$> auto) $ metavar "QUERY" <> help "SearchQuery" diff --git a/recycle-client/recycle-client.cabal b/recycle-client/recycle-client.cabal deleted file mode 100644 index c60dc6b..0000000 --- a/recycle-client/recycle-client.cabal +++ /dev/null @@ -1,182 +0,0 @@ -cabal-version: 3.4 --- Initial package description 'recycle-client.cabal' generated by 'cabal init'. --- For further documentation, see http://haskell.org/cabal/users-guide/ - -name: recycle-client -version: 0.2.0.0 -synopsis: recycleapp.be API and client -description: API definition and client for the recycleapp.be API --- bug-reports: -license: MIT -license-file: LICENSE -author: Brecht Serckx -maintainer: services+git@brechtserckx.be -copyright: (c) 2021-2022 Brecht Serckx -category: API -build-type: Simple -extra-source-files: - test/responses/*.json - --- Not 9.4.8 as in LTS, but highest current haskell-ci supports. -Tested-With: GHC ==9.4.5 - -common common-default-extensions - default-language: Haskell2010 - default-extensions: - ApplicativeDo - DataKinds - DeriveAnyClass - DeriveGeneric - DerivingVia - DuplicateRecordFields - EmptyCase - FlexibleContexts - FlexibleInstances - GADTs - GeneralizedNewtypeDeriving - InstanceSigs - LambdaCase - MultiParamTypeClasses - MultiWayIf - NamedFieldPuns - NoFieldSelectors - OverloadedRecordDot - OverloadedStrings - PackageImports - PatternSynonyms - RecordWildCards - ScopedTypeVariables - StandaloneDeriving - StrictData - TemplateHaskell - TupleSections - TypeApplications - ViewPatterns - -library - import: common-default-extensions - hs-source-dirs: src - ghc-options: - -Wall - exposed-modules: - Recycle.API - Recycle.AppM - Recycle.Class - Recycle.Types - Recycle.Types.LangCode - Recycle.Types.Error - Recycle.Types.Geo - Recycle.Utils - other-modules: - Paths_recycle_client - autogen-modules: - Paths_recycle_client - build-depends: - base - - -- data - , containers - , generic-lens - , sop-core - , text - , time - - -- effects - , capability - , mtl - , transformers - , safe-exceptions - , retry - , exceptions - - -- serialisation - , aeson - , aeson-extra - , deriving-aeson - , http-api-data - - -- network - , http-client - , http-client-tls - , http-media - , servant - , servant-client - , wai - - -- logging - , co-log - , co-log-core - -library recycle-client-optparse-applicative - import: common-default-extensions - visibility: public - hs-source-dirs: src-optparse-applicative - ghc-options: - -Wall - exposed-modules: - Recycle.Types.Optparse - build-depends: - base - , recycle-client - - -- cli - , optparse-applicative - -executable recycle-client - import: common-default-extensions - main-is: Main.hs - hs-source-dirs: app - ghc-options: - -Wall - -threaded - -rtsopts - -with-rtsopts=-N - other-modules: - Opts - build-depends: - base - , recycle-client - , recycle-client:recycle-client-optparse-applicative - - -- data - , bytestring - , text - , time - - -- serialisation - , aeson - - -- network - , http-client - , http-client-tls - , servant-client - - -- logging - , co-log - , co-log-core - - -- cli - , optparse-applicative - -test-suite recycle-client-test - import: common-default-extensions - type: exitcode-stdio-1.0 - main-is: Spec.hs - hs-source-dirs: test - ghc-options: - -threaded - -rtsopts - -with-rtsopts=-N - build-depends: - base - , recycle-client - , QuickCheck - , aeson - , aeson-extra - , bytestring - , containers - , file-embed - , hspec - , text - , time - , vector \ No newline at end of file diff --git a/recycle-client/recycle-client.sh b/recycle-client/recycle-client.sh deleted file mode 100755 index 6842b75..0000000 --- a/recycle-client/recycle-client.sh +++ /dev/null @@ -1,55 +0,0 @@ -#! /usr/bin/env bash -# shellcheck disable=SC3030,SC3024,SC3054 - -SECRET="" - -# get access token -# CMD=( -# get-access-token -# ) -ACCESS_TOKEN="" - -# search a zip code -# CMD=( -# search-zipcodes \ -# --access-token "$ACCESS_TOKEN" \ -# 3000 -# ) -ZIP_CODE="1234-56789" - -# search a street -# CMD=( -# search-streets \ -# --access-token "$ACCESS_TOKEN" -# --zipcode "$ZIP_CODE" -# Grote -# ) -STREET="https://data.vlaanderen.be/id/straatnaam-12345" - -HOUSE_NUMBER=1 - -# get the fractions for an address -# CMD=( -# get-fractions \ -# --zipcode "$ZIP_CODE" \ -# --street "$STREET" \ -# --house-number "$HOUSE_NUMBER" \ -# ) - -# get the collections for an address -CMD=( - get-collections \ - --zipcode "$ZIP_CODE" \ - --street "$STREET" \ - --house-number "$HOUSE_NUMBER" \ - ) -# use absolute date -# CMD+=(--absolute-from 2022-01-01 --absolute-to 2022-12-31) -# use relative date -CMD+=(--relative-from -14 --relative-to 14) - -# run it -cabal run exe:recycle-client -- \ - --secret "$SECRET" \ - "${CMD[@]}" \ - "$@" diff --git a/recycle-ics/app/Opts.hs b/recycle-ics/app/Opts.hs index dc1f303..7b926a9 100644 --- a/recycle-ics/app/Opts.hs +++ b/recycle-ics/app/Opts.hs @@ -4,17 +4,17 @@ module Opts parseOpts, GenerateIcsOpts (..), ServeIcsOpts (..), - module Recycle.Types.Optparse, + module Parsers, ) where import Colog (Severity (..)) import qualified Data.Char as Char import Options.Applicative +import Parsers import Recycle.Ics.ICalendar import Recycle.Ics.Types import Recycle.Types -import Recycle.Types.Optparse import Text.Read (readMaybe) data Opts = Opts diff --git a/recycle-client/src-optparse-applicative/Recycle/Types/Optparse.hs b/recycle-ics/app/Parsers.hs similarity index 98% rename from recycle-client/src-optparse-applicative/Recycle/Types/Optparse.hs rename to recycle-ics/app/Parsers.hs index e7e5dbd..5988e99 100644 --- a/recycle-client/src-optparse-applicative/Recycle/Types/Optparse.hs +++ b/recycle-ics/app/Parsers.hs @@ -1,4 +1,4 @@ -module Recycle.Types.Optparse +module Parsers ( ApiClientOpts (..), pApiClientOpts, pZipcodeId, diff --git a/recycle-ics/recycle-ics.cabal b/recycle-ics/recycle-ics.cabal index 21949e5..47481d6 100644 --- a/recycle-ics/recycle-ics.cabal +++ b/recycle-ics/recycle-ics.cabal @@ -14,6 +14,8 @@ maintainer: services+git@brechtserckx.be copyright: (c) 2021-2022 Brecht Serckx category: Service build-type: Simple +extra-source-files: + test/responses/*.json -- Not 9.4.8 as in LTS, but highest current haskell-ci supports. Tested-With: GHC ==9.4.5 @@ -22,6 +24,7 @@ common common-default-extensions default-language: Haskell2010 default-extensions: ApplicativeDo + DataKinds DeriveAnyClass DeriveGeneric DerivingVia @@ -56,6 +59,14 @@ library ghc-options: -Wall exposed-modules: + Recycle.API + Recycle.AppM + Recycle.Class + Recycle.Types + Recycle.Types.LangCode + Recycle.Types.Error + Recycle.Types.Geo + Recycle.Utils Recycle.Ics.ICalendar Recycle.Ics.Types Recycle.Ics.API @@ -68,7 +79,6 @@ library Paths_recycle_ics build-depends: base - , recycle-client -- data , bytestring @@ -86,6 +96,9 @@ library , capability , mtl , transformers + , safe-exceptions + , retry + , exceptions -- serialisation , aeson @@ -118,6 +131,7 @@ executable recycle-ics hs-source-dirs: app other-modules: Opts + Parsers Paths_recycle_ics autogen-modules: Paths_recycle_ics @@ -129,13 +143,12 @@ executable recycle-ics build-depends: base , recycle-ics - , recycle-client - , recycle-client:recycle-client-optparse-applicative -- data , bytestring , filepath , text + , time -- serialisation , aeson @@ -158,3 +171,26 @@ executable recycle-ics -- system , th-env , typed-process + +test-suite recycle-ics-test + import: common-default-extensions + type: exitcode-stdio-1.0 + main-is: Spec.hs + hs-source-dirs: test + ghc-options: + -threaded + -rtsopts + -with-rtsopts=-N + build-depends: + recycle-ics + , base + , QuickCheck + , aeson + , aeson-extra + , bytestring + , containers + , file-embed + , hspec + , text + , time + , vector diff --git a/recycle-client/src/Recycle/API.hs b/recycle-ics/src/Recycle/API.hs similarity index 100% rename from recycle-client/src/Recycle/API.hs rename to recycle-ics/src/Recycle/API.hs diff --git a/recycle-client/src/Recycle/AppM.hs b/recycle-ics/src/Recycle/AppM.hs similarity index 100% rename from recycle-client/src/Recycle/AppM.hs rename to recycle-ics/src/Recycle/AppM.hs diff --git a/recycle-client/src/Recycle/Class.hs b/recycle-ics/src/Recycle/Class.hs similarity index 100% rename from recycle-client/src/Recycle/Class.hs rename to recycle-ics/src/Recycle/Class.hs diff --git a/recycle-client/src/Recycle/Types.hs b/recycle-ics/src/Recycle/Types.hs similarity index 100% rename from recycle-client/src/Recycle/Types.hs rename to recycle-ics/src/Recycle/Types.hs diff --git a/recycle-client/src/Recycle/Types/Error.hs b/recycle-ics/src/Recycle/Types/Error.hs similarity index 100% rename from recycle-client/src/Recycle/Types/Error.hs rename to recycle-ics/src/Recycle/Types/Error.hs diff --git a/recycle-client/src/Recycle/Types/Geo.hs b/recycle-ics/src/Recycle/Types/Geo.hs similarity index 100% rename from recycle-client/src/Recycle/Types/Geo.hs rename to recycle-ics/src/Recycle/Types/Geo.hs diff --git a/recycle-client/src/Recycle/Types/LangCode.hs b/recycle-ics/src/Recycle/Types/LangCode.hs similarity index 100% rename from recycle-client/src/Recycle/Types/LangCode.hs rename to recycle-ics/src/Recycle/Types/LangCode.hs diff --git a/recycle-client/src/Recycle/Utils.hs b/recycle-ics/src/Recycle/Utils.hs similarity index 100% rename from recycle-client/src/Recycle/Utils.hs rename to recycle-ics/src/Recycle/Utils.hs diff --git a/recycle-client/test/Spec.hs b/recycle-ics/test/Spec.hs similarity index 100% rename from recycle-client/test/Spec.hs rename to recycle-ics/test/Spec.hs diff --git a/recycle-client/test/responses/authResult.json b/recycle-ics/test/responses/authResult.json similarity index 100% rename from recycle-client/test/responses/authResult.json rename to recycle-ics/test/responses/authResult.json diff --git a/recycle-client/test/responses/collection-event.json b/recycle-ics/test/responses/collection-event.json similarity index 100% rename from recycle-client/test/responses/collection-event.json rename to recycle-ics/test/responses/collection-event.json diff --git a/recycle-client/test/responses/collection-fraction-exception.json b/recycle-ics/test/responses/collection-fraction-exception.json similarity index 100% rename from recycle-client/test/responses/collection-fraction-exception.json rename to recycle-ics/test/responses/collection-fraction-exception.json diff --git a/recycle-client/test/responses/collection-fraction.json b/recycle-ics/test/responses/collection-fraction.json similarity index 100% rename from recycle-client/test/responses/collection-fraction.json rename to recycle-ics/test/responses/collection-fraction.json diff --git a/recycle-client/test/responses/collections.json b/recycle-ics/test/responses/collections.json similarity index 100% rename from recycle-client/test/responses/collections.json rename to recycle-ics/test/responses/collections.json diff --git a/recycle-client/test/responses/fractions.json b/recycle-ics/test/responses/fractions.json similarity index 100% rename from recycle-client/test/responses/fractions.json rename to recycle-ics/test/responses/fractions.json diff --git a/recycle-client/test/responses/streets.json b/recycle-ics/test/responses/streets.json similarity index 100% rename from recycle-client/test/responses/streets.json rename to recycle-ics/test/responses/streets.json diff --git a/recycle-client/test/responses/zipcodes.json b/recycle-ics/test/responses/zipcodes.json similarity index 100% rename from recycle-client/test/responses/zipcodes.json rename to recycle-ics/test/responses/zipcodes.json diff --git a/shell.nix b/shell.nix index 51acdcb..e47b46e 100644 --- a/shell.nix +++ b/shell.nix @@ -4,7 +4,6 @@ let nixpkgs-act = import sources.nixpkgs-act {}; in hsPkgs.shellFor { packages = ps: with ps; [ - recycle-client recycle-ics ]; diff --git a/stack.yaml b/stack.yaml index 0f818e5..bc9d224 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,6 +1,5 @@ flags: {} packages: - - './recycle-client/' - './recycle-ics/' extra-deps: - git: https://github.com/schoettl/iCalendar.git