diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..5809acd --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,62 @@ +name: Build + +on: + push: + branches: [master] + pull_request: + branches: [master] + release: + types: [prereleased] + +jobs: + check_versions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Check library version + if: github.event_name == 'release' + run: | + if [ "$(yq eval ".version" package.yaml)" != "${{ github.event.release.tag_name }}" ]; then + echo "::error file=action.yaml::Library version does not match release version." + exit 1 + fi + Linux: + needs: check_versions + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Cache + uses: actions/cache@v1 + with: + path: | + ~/.stack + .stack-work + key: ${{ runner.os }}-stack-${{ hashFiles('stack.yaml') }}-${{ hashFiles('package.yaml') }} + restore-keys: | + ${{ runner.os }}-stack-${{ hashFiles('stack.yaml') }} + ${{ runner.os }}-stack + + - name: Upgrade stack + shell: bash + run: stack upgrade --git + + - name: Build + shell: bash + run: | + stack build + + - name: Check Formatting + shell: bash + run: | + stack install ormolu + ormolu -o -XTypeApplications -o -XCPP -m check $(find src -type f -name "*.hs") + + - name: Publish candidate + shell: bash + if: github.event_name == 'release' + env: + HACKAGE_KEY: ${{ secrets.HACKAGE_TOKEN }} + run: | + stack upload --pvp-bounds both --test-tarball --candidate . diff --git a/Changelog.md b/Changelog.md new file mode 100644 index 0000000..b36483c --- /dev/null +++ b/Changelog.md @@ -0,0 +1,3 @@ +# 0.1.0.0 + +Initial release diff --git a/package.yaml b/package.yaml index 82b57ca..36e5f6e 100644 --- a/package.yaml +++ b/package.yaml @@ -1,18 +1,33 @@ name: deriving-openapi3 -version: 0.1.0 +version: 0.1.0.0 synopsis: DerivingVia for OpenAPI 3 -# description: +description: See for more details. maintainer: Ilya Kostyuchenko +category: JSON, Generics, OpenAPI +license: MIT +license-file: LICENSE +extra-source-files: Changelog.md github: ilyakooo0/deriving-openapi3 -ghc-options: -Wall +ghc-options: -Weverything + -Wno-star-is-type + -Wno-unsafe + -Wno-prepositive-qualified-module + -Wno-safe + -Wno-missing-safe-haskell-mode + -Wno-missing-import-lists + -Wno-implicit-prelude dependencies: - base - openapi3 - deriving-aeson - aeson - - servant - lens - text +when: + - condition: flag(servant-description) + dependencies: + - servant + cpp-options: -DSERVANT_DESCRIPTION library: source-dirs: src default-extensions: @@ -27,3 +42,8 @@ default-extensions: - TypeFamilies - PolyKinds - OverloadedStrings +flags: + servant-description: + description: Create instances for the 'Description' type from 'servant' + default: true + manual: false diff --git a/src/Deriving/OpenApi.hs b/src/Deriving/OpenApi.hs index 8e61f36..61c165f 100644 --- a/src/Deriving/OpenApi.hs +++ b/src/Deriving/OpenApi.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -Wno-orphans #-} module Deriving.OpenApi @@ -15,13 +16,28 @@ import Data.Kind import Data.OpenApi import Data.OpenApi.Internal.Schema import Data.Proxy -import Data.Text (Text) -import qualified Data.Text as T import Data.Typeable import Deriving.Aeson import GHC.Generics import GHC.TypeLits + +#ifdef SERVANT_DESCRIPTION + import Servant.API +import Data.Text (Text) +import qualified Data.Text as T + +instance (AesonOptions xs) => AesonOptions (Description f ': xs) where + aesonOptions = aesonOptions @xs + +instance (OpenApiOptions xs, KnownSymbol t) => OpenApiOptions (Description t ': xs) where + openApiOptions = openApiOptions @xs + openApiSchemaModifier = schema . description <>~ Just (toTextLine @t) + +toTextLine :: forall s. KnownSymbol s => Text +toTextLine = "\n\n" <> T.pack (symbolVal (Proxy @s)) + +#endif type CustomOpenApi = CustomJSON @@ -37,16 +53,6 @@ instance (StringModifier f, OpenApiOptions xs) => OpenApiOptions (DatatypeNameMo instance (AesonOptions xs) => AesonOptions (DatatypeNameModifier f ': xs) where aesonOptions = aesonOptions @xs -instance (AesonOptions xs) => AesonOptions (Description f ': xs) where - aesonOptions = aesonOptions @xs - -instance (OpenApiOptions xs, KnownSymbol t) => OpenApiOptions (Description t ': xs) where - openApiOptions = openApiOptions @xs - openApiSchemaModifier = schema . description <>~ Just (toTextLine @t) - -toTextLine :: forall s. KnownSymbol s => Text -toTextLine = "\n\n" <> T.pack (symbolVal (Proxy @s)) - type family (++) (x :: [k]) (y :: [k]) :: [k] where (++) '[] ys = ys (++) (x ': xs) ys = xs ++ (x ': ys)