packages feed

deriving-openapi3 (empty) → 0.1.0.0

raw patch · 4 files changed

+205/−0 lines, 4 filesdep +aesondep +basedep +deriving-aeson

Dependencies added: aeson, base, deriving-aeson, lens, openapi3, text

Files

+ Changelog.md view
@@ -0,0 +1,3 @@+# 0.1.0.0++Initial release
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2022 Ilya Kostyuchenko++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.
+ deriving-openapi3.cabal view
@@ -0,0 +1,42 @@+cabal-version:      1.12+name:               deriving-openapi3+version:            0.1.0.0+license:            MIT+license-file:       LICENSE+maintainer:         Ilya Kostyuchenko <ilyakooo0@gmail.com>+homepage:           https://github.com/ilyakooo0/deriving-openapi3#readme+bug-reports:        https://github.com/ilyakooo0/deriving-openapi3/issues+synopsis:           DerivingVia for OpenAPI 3+description:        DerivingVia for OpenAPI 3+category:           JSON, Generics, OpenAPI+build-type:         Simple+extra-source-files: Changelog.md++source-repository head+    type:     git+    location: https://github.com/ilyakooo0/deriving-openapi3++library+    exposed-modules:    Deriving.OpenApi+    hs-source-dirs:     src+    other-modules:      Paths_deriving_openapi3+    default-language:   Haskell2010+    default-extensions:+        AllowAmbiguousTypes ScopedTypeVariables KindSignatures DataKinds+        TypeOperators FlexibleInstances TypeApplications+        UndecidableInstances TypeFamilies PolyKinds OverloadedStrings+        DerivingStrategies DerivingVia FlexibleContexts++    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++    build-depends:+        aeson <1.6,+        base <4.15,+        deriving-aeson <0.3,+        lens <4.20,+        openapi3 <3.2,+        text <1.3
+ src/Deriving/OpenApi.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wno-orphans #-}++-- | __Example:__+--+-- >>> :set -XDerivingStrategies -XDerivingVia -XDeriveGeneric+--+-- >>> :{+-- data User = User+--   { userFirstName :: String,+--     userAge :: Maybe Integer+--   }+--   deriving stock (Generic)+--   deriving (FromJSON, ToJSON, ToSchema)+--     via CustomJSON+--          '[FieldLabelModifier '[StripPrefix "user", CamelToSnake], RejectUnknownFields]+--          User+-- showYaml = Data.ByteString.Char8.putStr . Data.Yaml.encode+-- :}+--+-- >>> showYaml $ toSchema (Proxy :: Proxy User)+-- type: object+-- properties:+--   first_name:+--     type: string+--   age:+--     type: integer+-- required:+-- - first_name+-- additionalProperties: false+module Deriving.OpenApi+  ( CustomOpenApi,+    DatatypeNameModifier,+    ToSchema,+    module Deriving.Aeson,+  )+where++import Control.Lens+import qualified Data.Aeson.Types as A+import Data.OpenApi+import Data.OpenApi.Internal.ParamSchema+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++data Description (desc :: Symbol) = Description++instance (AesonOptions xs) => AesonOptions (Description f ': xs) where+  aesonOptions = aesonOptions @xs++instance KnownSymbol t => OpenApiOptionModifier (Description t) where+  openApiSchemaModifier = schema . description <>~ Just (toTextLine @t)++toTextLine :: forall s. KnownSymbol s => Text+toTextLine = "\n\n" <> T.pack (symbolVal (Proxy @s))++-- $setup+-- >>> import qualified Data.Yaml+-- >>> import qualified Data.ByteString.Char8++type CustomOpenApi = CustomJSON++instance+  (OpenApiOptionModifier xs, GToSchema (Rep x), Generic x, Typeable x, Typeable xs, Typeable k) =>+  ToSchema (CustomJSON (xs :: k) x)+  where+  declareNamedSchema Proxy =+    openApiSchemaModifier @xs+      <$> genericDeclareNamedSchema (openApiOptionsModifier @xs defaultSchemaOptions) (Proxy @x)++instance+  (OpenApiOptionModifier xs, GToParamSchema (Rep x), Generic x) =>+  ToParamSchema (CustomJSON (xs :: k) x)+  where+  toParamSchema Proxy =+    genericToParamSchema (openApiOptionsModifier @xs defaultSchemaOptions) (Proxy @x)++class OpenApiOptionModifier x where+  openApiOptionsModifier :: SchemaOptions -> SchemaOptions+  openApiOptionsModifier = id+  openApiSchemaModifier :: NamedSchema -> NamedSchema+  openApiSchemaModifier = id++data DatatypeNameModifier t++instance (StringModifier f) => OpenApiOptionModifier (DatatypeNameModifier f) where+  openApiOptionsModifier o = o {datatypeNameModifier = getStringModifier @f}++instance (AesonOptions xs) => AesonOptions (DatatypeNameModifier f ': xs) where+  aesonOptions = aesonOptions @xs++-- deriving-aeson-based instances++instance OpenApiOptionModifier UnwrapUnaryRecords where+  openApiOptionsModifier o = o {unwrapUnaryRecords = True}++instance OpenApiOptionModifier OmitNothingFields++#if MIN_VERSION_deriving_aeson(0,2,4)+instance OpenApiOptionModifier RejectUnknownFields where+  openApiSchemaModifier = schema . additionalProperties .~ Just (AdditionalPropertiesAllowed False)+#endif++instance StringModifier f => OpenApiOptionModifier (FieldLabelModifier f) where+  openApiOptionsModifier o = o {fieldLabelModifier = getStringModifier @f}++instance StringModifier f => OpenApiOptionModifier (ConstructorTagModifier f) where+  openApiOptionsModifier o = o {constructorTagModifier = getStringModifier @f}++instance+  TypeError ('Text "deriving-openapi3 does not currently the `TagSingleConstructors` modifier.") =>+  OpenApiOptionModifier TagSingleConstructors++instance OpenApiOptionModifier NoAllNullaryToStringTag where+  openApiOptionsModifier o = o {allNullaryToStringTag = False}++instance (KnownSymbol t, KnownSymbol c) => OpenApiOptionModifier (SumTaggedObject t c) where+  openApiOptionsModifier o = o {sumEncoding = A.TaggedObject (symbolVal (Proxy @t)) (symbolVal (Proxy @c))}++instance OpenApiOptionModifier SumUntaggedValue where+  openApiOptionsModifier o = o {sumEncoding = A.UntaggedValue}++instance OpenApiOptionModifier SumObjectWithSingleField where+  openApiOptionsModifier o = o {sumEncoding = A.ObjectWithSingleField}++instance OpenApiOptionModifier SumTwoElemArray where+  openApiOptionsModifier o = o {sumEncoding = A.TwoElemArray}++instance OpenApiOptionModifier '[]++instance (OpenApiOptionModifier x, OpenApiOptionModifier xs) => OpenApiOptionModifier (x ': xs) where+  openApiOptionsModifier = openApiOptionsModifier @xs . openApiOptionsModifier @x+  openApiSchemaModifier = openApiSchemaModifier @xs . openApiSchemaModifier @x