Skip to content

Commit

Permalink
WPB-4240: Migrate from swagger2 to openapi3 (#3570)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Igor Ranieri Elland <54423+elland@users.noreply.github.com>
Co-authored-by: Igor Ranieri <igor@elland.me>
  • Loading branch information
3 people authored and supersven committed Oct 4, 2023
1 parent f7f28c4 commit 326eb84
Show file tree
Hide file tree
Showing 191 changed files with 890 additions and 579 deletions.
1 change: 1 addition & 0 deletions changelog.d/4-docs/WPB-4240
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Updating the route documentation from Swagger 2 to OpenAPI 3.
4 changes: 4 additions & 0 deletions changelog.d/5-internal/WPB-4240
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Updating the route documentation library from swagger2 to openapi3.

This also introduced a breaking change in how we track what federation calls each route makes.
The openapi3 library doesn't support extension fields, and as such tags are being used instead in a similar way.
2 changes: 1 addition & 1 deletion libs/brig-types/brig-types.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ test-suite brig-types-tests
, brig-types
, bytestring-conversion >=0.3.1
, imports
, openapi3
, QuickCheck >=2.9
, swagger2 >=2.5
, tasty
, tasty-hunit
, tasty-quickcheck
Expand Down
4 changes: 2 additions & 2 deletions libs/brig-types/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
, gitignoreSource
, imports
, lib
, openapi3
, QuickCheck
, swagger2
, tasty
, tasty-hunit
, tasty-quickcheck
Expand Down Expand Up @@ -47,8 +47,8 @@ mkDerivation {
base
bytestring-conversion
imports
openapi3
QuickCheck
swagger2
tasty
tasty-hunit
tasty-quickcheck
Expand Down
4 changes: 2 additions & 2 deletions libs/brig-types/test/unit/Test/Brig/Roundtrip.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module Test.Brig.Roundtrip where
import Data.Aeson (FromJSON, ToJSON, parseJSON, toJSON)
import Data.Aeson.Types (parseEither)
import Data.ByteString.Conversion
import Data.Swagger (ToSchema, validatePrettyToJSON)
import Data.OpenApi (ToSchema, validatePrettyToJSON)
import Imports
import Test.Tasty (TestTree)
import Test.Tasty.QuickCheck (Arbitrary, counterexample, testProperty, (.&&.), (===))
Expand All @@ -40,7 +40,7 @@ testRoundTrip = testProperty msg trip

testRoundTripWithSwagger ::
forall a.
(Arbitrary a, Typeable a, ToJSON a, FromJSON a, ToSchema a, Eq a, Show a) =>
(Arbitrary a, ToJSON a, FromJSON a, ToSchema a, Eq a, Show a) =>
TestTree
testRoundTripWithSwagger = testProperty msg (trip .&&. scm)
where
Expand Down
4 changes: 2 additions & 2 deletions libs/deriving-swagger2/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
, gitignoreSource
, imports
, lib
, swagger2
, openapi3
}:
mkDerivation {
pname = "deriving-swagger2";
version = "0.1.0";
src = gitignoreSource ./.;
libraryHaskellDepends = [ base extra imports swagger2 ];
libraryHaskellDepends = [ base extra imports openapi3 ];
license = lib.licenses.agpl3Only;
}
4 changes: 2 additions & 2 deletions libs/deriving-swagger2/deriving-swagger2.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ library
-Wredundant-constraints -Wunused-packages

build-depends:
base >=4 && <5
base >=4 && <5
, extra
, imports
, swagger2 >=0.6
, openapi3

default-language: GHC2021
18 changes: 7 additions & 11 deletions libs/deriving-swagger2/src/Deriving/Swagger.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{-# LANGUAGE RankNTypes #-}

-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
Expand All @@ -22,10 +24,10 @@ module Deriving.Swagger where
import Data.Char qualified as Char
import Data.Kind (Constraint)
import Data.List.Extra (stripSuffix)
import Data.OpenApi.Internal.Schema (GToSchema)
import Data.OpenApi.Internal.TypeShape
import Data.OpenApi.Schema
import Data.Proxy (Proxy (..))
import Data.Swagger (SchemaOptions, ToSchema (..), constructorTagModifier, defaultSchemaOptions, fieldLabelModifier, genericDeclareNamedSchema)
import Data.Swagger.Internal.Schema (GToSchema)
import Data.Swagger.Internal.TypeShape (TypeHasSimpleShape)
import GHC.Generics (Generic (Rep))
import GHC.TypeLits (ErrorMessage (Text), KnownSymbol, Symbol, TypeError, symbolVal)
import Imports
Expand Down Expand Up @@ -81,6 +83,7 @@ import Imports
-- | A newtype wrapper which gives ToSchema instances with modified options.
-- 't' has to have an instance of the 'SwaggerOptions' class.
newtype CustomSwagger t a = CustomSwagger {unCustomSwagger :: a}
deriving (Generic, Typeable)

class SwaggerOptions xs where
swaggerOptions :: SchemaOptions
Expand All @@ -94,14 +97,7 @@ instance (StringModifier f, SwaggerOptions xs) => SwaggerOptions (FieldLabelModi
instance (StringModifier f, SwaggerOptions xs) => SwaggerOptions (ConstructorTagModifier f ': xs) where
swaggerOptions = (swaggerOptions @xs) {constructorTagModifier = getStringModifier @f}

instance
( SwaggerOptions t,
Generic a,
GToSchema (Rep a),
TypeHasSimpleShape a "genericDeclareNamedSchemaUnrestricted"
) =>
ToSchema (CustomSwagger t a)
where
instance (SwaggerOptions t, Generic a, Typeable a, GToSchema (Rep a), Typeable (CustomSwagger t a), TypeHasSimpleShape a "genericDeclareNamedSchemaUnrestricted") => ToSchema (CustomSwagger t a) where
declareNamedSchema _ = genericDeclareNamedSchema (swaggerOptions @t) (Proxy @a)

-- ** Specify __what__ to modify
Expand Down
4 changes: 2 additions & 2 deletions libs/extended/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
, servant
, servant-client
, servant-client-core
, servant-openapi3
, servant-server
, servant-swagger
, temporary
, text
, tinylog
Expand Down Expand Up @@ -60,8 +60,8 @@ mkDerivation {
servant
servant-client
servant-client-core
servant-openapi3
servant-server
servant-swagger
text
tinylog
unliftio
Expand Down
2 changes: 1 addition & 1 deletion libs/extended/extended.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ library
, servant
, servant-client
, servant-client-core
, servant-openapi3
, servant-server
, servant-swagger
, text
, tinylog
, unliftio
Expand Down
8 changes: 4 additions & 4 deletions libs/extended/src/Servant/API/Extended.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ import Network.Wai
import Servant.API
import Servant.API.ContentTypes
import Servant.API.Modifiers
import Servant.OpenApi
import Servant.Server.Internal
import Servant.Swagger
import Prelude ()

-- | Like 'ReqBody'', but takes parsers that throw 'ServerError', not 'String'. @tag@ is used
Expand Down Expand Up @@ -108,10 +108,10 @@ instance
Right v -> pure v

instance
HasSwagger (ReqBody' '[Required, Strict] cts a :> api) =>
HasSwagger (ReqBodyCustomError cts tag a :> api)
HasOpenApi (ReqBody' '[Required, Strict] cts a :> api) =>
HasOpenApi (ReqBodyCustomError cts tag a :> api)
where
toSwagger Proxy = toSwagger (Proxy @(ReqBody' '[Required, Strict] cts a :> api))
toOpenApi Proxy = toOpenApi (Proxy @(ReqBody' '[Required, Strict] cts a :> api))

instance RoutesToPaths rest => RoutesToPaths (ReqBodyCustomError' mods list tag a :> rest) where
getRoutes = getRoutes @rest
6 changes: 3 additions & 3 deletions libs/extended/src/Servant/API/Extended/RawM.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import Data.Proxy
import Imports
import Network.Wai
import Servant.API (Raw)
import Servant.OpenApi
import Servant.Server hiding (respond)
import Servant.Server.Internal.Delayed
import Servant.Server.Internal.RouteResult
import Servant.Server.Internal.Router
import Servant.Swagger

type ApplicationM m = Request -> (Response -> IO ResponseReceived) -> m ResponseReceived

Expand Down Expand Up @@ -51,8 +51,8 @@ instance HasServer RawM context where

hoistServerWithContext _ _ f srvM req respond = f (srvM req respond)

instance HasSwagger RawM where
toSwagger _ = toSwagger (Proxy @Raw)
instance HasOpenApi RawM where
toOpenApi _ = toOpenApi (Proxy @Raw)

instance RoutesToPaths RawM where
getRoutes = []
6 changes: 3 additions & 3 deletions libs/schema-profunctor/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
, insert-ordered-containers
, lens
, lib
, openapi3
, profunctors
, swagger2
, tasty
, tasty-hunit
, text
Expand All @@ -34,8 +34,8 @@ mkDerivation {
containers
imports
lens
openapi3
profunctors
swagger2
text
transformers
vector
Expand All @@ -47,7 +47,7 @@ mkDerivation {
imports
insert-ordered-containers
lens
swagger2
openapi3
tasty
tasty-hunit
text
Expand Down
4 changes: 2 additions & 2 deletions libs/schema-profunctor/schema-profunctor.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ library
, containers
, imports
, lens
, openapi3
, profunctors
, swagger2 >=2 && <2.9
, text
, transformers
, vector
Expand Down Expand Up @@ -139,8 +139,8 @@ test-suite schemas-tests
, imports
, insert-ordered-containers
, lens
, openapi3
, schema-profunctor
, swagger2
, tasty
, tasty-hunit
, text
Expand Down
34 changes: 20 additions & 14 deletions libs/schema-profunctor/src/Data/Schema.hs
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,11 @@ import Data.List.NonEmpty (NonEmpty)
import Data.List.NonEmpty qualified as NonEmpty
import Data.Map qualified as Map
import Data.Monoid hiding (Product)
import Data.OpenApi qualified as S
import Data.OpenApi.Declare qualified as S
import Data.Profunctor (Star (..))
import Data.Proxy (Proxy (..))
import Data.Set qualified as Set
import Data.Swagger qualified as S
import Data.Swagger.Declare qualified as S
import Data.Swagger.Internal qualified as S
import Data.Text qualified as T
import Data.Text.Lazy qualified as TL
import Data.Vector qualified as V
Expand Down Expand Up @@ -624,7 +623,7 @@ text name =
(A.withText (T.unpack name) pure)
(pure . A.String)
where
d = mempty & S.type_ ?~ S.SwaggerString
d = mempty & S.type_ ?~ S.OpenApiString

-- | A schema for a textual value with possible failure.
parsedText ::
Expand Down Expand Up @@ -764,7 +763,7 @@ instance HasSchemaRef doc => HasField doc SwaggerDoc where
where
f ref =
mempty
& S.type_ ?~ S.SwaggerObject
& S.type_ ?~ S.OpenApiObject
& S.properties . at name ?~ ref
& S.required .~ [name]

Expand All @@ -780,16 +779,16 @@ instance HasSchemaRef ndoc => HasArray ndoc SwaggerDoc where
f :: S.Referenced S.Schema -> S.Schema
f ref =
mempty
& S.type_ ?~ S.SwaggerArray
& S.items ?~ S.SwaggerItemsObject ref
& S.type_ ?~ S.OpenApiArray
& S.items ?~ S.OpenApiItemsObject ref

instance HasSchemaRef ndoc => HasMap ndoc SwaggerDoc where
mkMap = fmap f . schemaRef
where
f :: S.Referenced S.Schema -> S.Schema
f ref =
mempty
& S.type_ ?~ S.SwaggerObject
& S.type_ ?~ S.OpenApiObject
& S.additionalProperties ?~ S.AdditionalPropertiesSchema ref

class HasMinItems s a where
Expand All @@ -799,19 +798,19 @@ instance HasMinItems SwaggerDoc (Maybe Integer) where
minItems = declared . S.minItems

instance HasEnum Text NamedSwaggerDoc where
mkEnum = mkSwaggerEnum S.SwaggerString
mkEnum = mkSwaggerEnum S.OpenApiString

instance HasEnum Integer NamedSwaggerDoc where
mkEnum = mkSwaggerEnum S.SwaggerInteger
mkEnum = mkSwaggerEnum S.OpenApiInteger

instance HasEnum Natural NamedSwaggerDoc where
mkEnum = mkSwaggerEnum S.SwaggerInteger
mkEnum = mkSwaggerEnum S.OpenApiInteger

instance HasEnum Bool NamedSwaggerDoc where
mkEnum = mkSwaggerEnum S.SwaggerBoolean
mkEnum = mkSwaggerEnum S.OpenApiBoolean

mkSwaggerEnum ::
S.SwaggerType 'S.SwaggerKindSchema ->
S.OpenApiType ->
Text ->
[A.Value] ->
NamedSwaggerDoc
Expand Down Expand Up @@ -839,11 +838,12 @@ class ToSchema a where
-- Newtype wrappers for deriving via

newtype Schema a = Schema {getSchema :: a}
deriving (Generic)

schemaToSwagger :: forall a. ToSchema a => Proxy a -> Declare S.NamedSchema
schemaToSwagger _ = runDeclare (schemaDoc (schema @a))

instance ToSchema a => S.ToSchema (Schema a) where
instance (Typeable a, ToSchema a) => S.ToSchema (Schema a) where
declareNamedSchema _ = schemaToSwagger (Proxy @a)

-- | JSON serialiser for an instance of 'ToSchema'.
Expand Down Expand Up @@ -920,8 +920,14 @@ instance S.HasSchema d S.Schema => S.HasSchema (SchemaP d v w a b) S.Schema wher
instance S.HasDescription NamedSwaggerDoc (Maybe Text) where
description = declared . S.schema . S.description

instance S.HasDeprecated NamedSwaggerDoc (Maybe Bool) where
deprecated = declared . S.schema . S.deprecated

instance {-# OVERLAPPABLE #-} S.HasDescription s a => S.HasDescription (WithDeclare s) a where
description = declared . S.description

instance {-# OVERLAPPABLE #-} S.HasDeprecated s a => S.HasDeprecated (WithDeclare s) a where
deprecated = declared . S.deprecated

instance {-# OVERLAPPABLE #-} S.HasExample s a => S.HasExample (WithDeclare s) a where
example = declared . S.example
Loading

0 comments on commit 326eb84

Please sign in to comment.