@@ -1,15 +1,17 @@
1{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE ConstraintKinds #-}
3+{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE DefaultSignatures #-}
4{-# LANGUAGE DefaultSignatures #-}
3{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE KindSignatures #-}
7{-# LANGUAGE KindSignatures #-}
6−{-# LANGUAGE DataKinds #-}
7{-# LANGUAGE OverloadedLists #-}
8{-# LANGUAGE OverloadedLists #-}
8{-# LANGUAGE OverloadedStrings #-}
9{-# LANGUAGE OverloadedStrings #-}
9{-# LANGUAGE PackageImports #-}
10{-# LANGUAGE PackageImports #-}
10{-# LANGUAGE PolyKinds #-}
11{-# LANGUAGE PolyKinds #-}
11{-# LANGUAGE ScopedTypeVariables #-}
12{-# LANGUAGE ScopedTypeVariables #-}
12{-# LANGUAGE TupleSections #-}
13{-# LANGUAGE TupleSections #-}
14+{-# LANGUAGE TypeApplications #-}
13{-# LANGUAGE TypeFamilies #-}
15{-# LANGUAGE TypeFamilies #-}
14{-# LANGUAGE TypeOperators #-}
16{-# LANGUAGE TypeOperators #-}
15{-# LANGUAGE TypeSynonymInstances #-}
17{-# LANGUAGE TypeSynonymInstances #-}
@@ -40,6 +42,7 @@ import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
40import Data.Int
42import Data.Int
41import Data.IntSet (IntSet)
43import Data.IntSet (IntSet)
42import Data.IntMap (IntMap)
44import Data.IntMap (IntMap)
45+import Data.List (sort)
43import Data.List.NonEmpty.Compat (NonEmpty)
46import Data.List.NonEmpty.Compat (NonEmpty)
44import Data.Map (Map)
47import Data.Map (Map)
45import Data.Maybe (fromMaybe)
48import Data.Maybe (fromMaybe)
@@ -59,14 +62,16 @@ import Numeric.Natural.Compat (Natural)
59import Data.Word
62import Data.Word
60import GHC.Generics
63import GHC.Generics
61import qualified Data.UUID.Types as UUID
64import qualified Data.UUID.Types as UUID
65+import Type.Reflection (Typeable, typeRep)
67+import Data.OpenApi.Aeson.Compat (keyToText, objectKeys, toInsOrdHashMap)
63−import Data.OpenApi.Declare
68+import Data.OpenApi.Declare
64−import Data.OpenApi.Internal
69+import Data.OpenApi.Internal
65−import Data.OpenApi.Internal.ParamSchema (ToParamSchema(..))
70+import Data.OpenApi.Internal.ParamSchema (ToParamSchema (..))
71+import Data.OpenApi.Internal.TypeShape
66−import Data.OpenApi.Lens hiding (name, schema)
72+import Data.OpenApi.Lens hiding (name, schema)
67−import qualified Data.OpenApi.Lens as Swagger
73+import qualified Data.OpenApi.Lens as Swagger
68−import Data.OpenApi.SchemaOptions
74+import Data.OpenApi.SchemaOptions
69−import Data.OpenApi.Internal.TypeShape
71import qualified Data.ByteString as BS
76import qualified Data.ByteString as BS
72import qualified Data.ByteString.Lazy.Char8 as BSL
77import qualified Data.ByteString.Lazy.Char8 as BSL
@@ -105,7 +110,7 @@ rename name (NamedSchema _ schema) = NamedSchema name schema
105-- declareNamedSchema _ = do
110-- declareNamedSchema _ = do
106-- doubleSchema <- declareSchemaRef (Proxy :: Proxy Double)
111-- doubleSchema <- declareSchemaRef (Proxy :: Proxy Double)
107-- return $ NamedSchema (Just \"Coord\") $ mempty
112-- return $ NamedSchema (Just \"Coord\") $ mempty
108−-- & type_ ?~ SwaggerObject
113+-- & type_ ?~ OpenApiObject
109-- & properties .~
114-- & properties .~
110-- [ (\"x\", doubleSchema)
115-- [ (\"x\", doubleSchema)
111-- , (\"y\", doubleSchema)
116-- , (\"y\", doubleSchema)
@@ -131,7 +136,7 @@ rename name (NamedSchema _ schema) = NamedSchema name schema
132-- instance ToSchema Coord
137-- instance ToSchema Coord
134−class ToSchema a where
139+class Typeable a => ToSchema a where
135 -- | Convert a type into an optionally named schema
140 -- | Convert a type into an optionally named schema
136 -- together with all used definitions.
141 -- together with all used definitions.
137 -- Note that the schema itself is included in definitions
142 -- Note that the schema itself is included in definitions
@@ -153,13 +158,19 @@ declareSchema = fmap _namedSchemaSchema . declareNamedSchema
154-- >>> toNamedSchema (Proxy :: Proxy String) ^. name
159-- >>> toNamedSchema (Proxy :: Proxy String) ^. name
155-- Nothing
160-- Nothing
156−-- >>> BSL.putStrLn $ encode (toNamedSchema (Proxy :: Proxy String) ^. schema)
161+-- >>> BSL.putStrLn $ encodePretty (toNamedSchema (Proxy :: Proxy String) ^. schema)
157−-- {"type":"string"}
163+-- "type": "string"
159-- >>> toNamedSchema (Proxy :: Proxy Day) ^. name
166-- >>> toNamedSchema (Proxy :: Proxy Day) ^. name
160-- Just "Day"
167-- Just "Day"
161−-- >>> BSL.putStrLn $ encode (toNamedSchema (Proxy :: Proxy Day) ^. schema)
168+-- >>> BSL.putStrLn $ encodePretty (toNamedSchema (Proxy :: Proxy Day) ^. schema)
162−-- {"example":"2016-07-22","format":"date","type":"string"}
170+-- "example": "2016-07-22",
163toNamedSchema :: ToSchema a => Proxy a -> NamedSchema
174toNamedSchema :: ToSchema a => Proxy a -> NamedSchema
164toNamedSchema = undeclare . declareNamedSchema
175toNamedSchema = undeclare . declareNamedSchema
@@ -175,22 +186,35 @@ schemaName = _namedSchemaName . toNamedSchema
176-- | Convert a type into a schema.
187-- | Convert a type into a schema.
178−-- >>> BSL.putStrLn $ encode $ toSchema (Proxy :: Proxy Int8)
189+-- >>> BSL.putStrLn $ encodePretty $ toSchema (Proxy :: Proxy Int8)
179−-- {"maximum":127,"minimum":-128,"type":"integer"}
193+-- "type": "integer"
181−-- >>> BSL.putStrLn $ encode $ toSchema (Proxy :: Proxy [Day])
196+-- >>> BSL.putStrLn $ encodePretty $ toSchema (Proxy :: Proxy [Day])
182−-- {"items":{"$ref":"#/components/schemas/Day"},"type":"array"}
199+-- "$ref": "#/components/schemas/Day"
183toSchema :: ToSchema a => Proxy a -> Schema
203toSchema :: ToSchema a => Proxy a -> Schema
184toSchema = _namedSchemaSchema . toNamedSchema
204toSchema = _namedSchemaSchema . toNamedSchema
186-- | Convert a type into a referenced schema if possible.
206-- | Convert a type into a referenced schema if possible.
187-- Only named schemas can be referenced, nameless schemas are inlined.
207-- Only named schemas can be referenced, nameless schemas are inlined.
189−-- >>> BSL.putStrLn $ encode $ toSchemaRef (Proxy :: Proxy Integer)
209+-- >>> BSL.putStrLn $ encodePretty $ toSchemaRef (Proxy :: Proxy Integer)
190−-- {"type":"integer"}
211+-- "type": "integer"
192−-- >>> BSL.putStrLn $ encode $ toSchemaRef (Proxy :: Proxy Day)
214+-- >>> BSL.putStrLn $ encodePretty $ toSchemaRef (Proxy :: Proxy Day)
193−-- {"$ref":"#/components/schemas/Day"}
216+-- "$ref": "#/components/schemas/Day"
194toSchemaRef :: ToSchema a => Proxy a -> Referenced Schema
218toSchemaRef :: ToSchema a => Proxy a -> Referenced Schema
195toSchemaRef = undeclare . declareSchemaRef
219toSchemaRef = undeclare . declareSchemaRef
@@ -258,8 +282,15 @@ inlineAllSchemas = inlineSchemasWhen (const True)
259-- | Convert a type into a schema without references.
283-- | Convert a type into a schema without references.
261−-- >>> BSL.putStrLn $ encode $ toInlinedSchema (Proxy :: Proxy [Day])
285+-- >>> BSL.putStrLn $ encodePretty $ toInlinedSchema (Proxy :: Proxy [Day])
262−-- {"items":{"example":"2016-07-22","format":"date","type":"string"},"type":"array"}
288+-- "example": "2016-07-22",
264-- __WARNING:__ @'toInlinedSchema'@ will produce infinite schema
295-- __WARNING:__ @'toInlinedSchema'@ will produce infinite schema
265-- when inlining recursive schemas.
296-- when inlining recursive schemas.
@@ -292,19 +323,64 @@ inlineNonRecursiveSchemas defs = inlineSchemasWhen nonRecursive defs
292-- | Make an unrestrictive sketch of a @'Schema'@ based on a @'ToJSON'@ instance.
323-- | Make an unrestrictive sketch of a @'Schema'@ based on a @'ToJSON'@ instance.
293-- Produced schema can be used for further refinement.
324-- Produced schema can be used for further refinement.
295−-- >>> BSL.putStrLn $ encode $ sketchSchema "hello"
326+-- >>> BSL.putStrLn $ encodePretty $ sketchSchema "hello"
296−-- {"example":"hello","type":"string"}
328+-- "example": "hello",
298−-- >>> BSL.putStrLn $ encode $ sketchSchema (1, 2, 3)
332+-- >>> BSL.putStrLn $ encodePretty $ sketchSchema (1, 2, 3)
299−-- {"example":[1,2,3],"items":{"type":"number"},"type":"array"}
340+-- "type": "number"
301−-- >>> BSL.putStrLn $ encode $ sketchSchema ("Jack", 25)
345+-- >>> BSL.putStrLn $ encodePretty $ sketchSchema ("Jack", 25)
302−-- {"example":["Jack",25],"items":[{"type":"string"},{"type":"number"}],"type":"array"}
346+-- {
304-- >>> data Person = Person { name :: String, age :: Int } deriving (Generic)
362-- >>> data Person = Person { name :: String, age :: Int } deriving (Generic)
305-- >>> instance ToJSON Person
363-- >>> instance ToJSON Person
306−-- >>> BSL.putStrLn $ encode $ sketchSchema (Person "Jack" 25)
364+-- >>> BSL.putStrLn $ encodePretty $ sketchSchema (Person "Jack" 25)
307−-- {"example":{"age":25,"name":"Jack"},"required":["age","name"],"type":"object","properties":{"age":{"type":"number"},"name":{"type":"string"}}}
365+-- {
308sketchSchema :: ToJSON a => a -> Schema
384sketchSchema :: ToJSON a => a -> Schema
309sketchSchema = sketch . toJSON
385sketchSchema = sketch . toJSON
@@ -312,15 +388,15 @@ sketchSchema = sketch . toJSON
312 sketch js@(Bool _) = go js
388 sketch js@(Bool _) = go js
313 sketch js = go js & example ?~ js
389 sketch js = go js & example ?~ js
315− go Null = mempty & type_ ?~ SwaggerNull
391+ go Null = mempty & type_ ?~ OpenApiNull
316− go (Bool _) = mempty & type_ ?~ SwaggerBoolean
392+ go (Bool _) = mempty & type_ ?~ OpenApiBoolean
317− go (String _) = mempty & type_ ?~ SwaggerString
393+ go (String _) = mempty & type_ ?~ OpenApiString
318− go (Number _) = mempty & type_ ?~ SwaggerNumber
394+ go (Number _) = mempty & type_ ?~ OpenApiNumber
319 go (Array xs) = mempty
395 go (Array xs) = mempty
320− & type_ ?~ SwaggerArray
396+ & type_ ?~ OpenApiArray
321 & items ?~ case ischema of
397 & items ?~ case ischema of
322− Just s -> SwaggerItemsObject (Inline s)
398+ Just s -> OpenApiItemsObject (Inline s)
323− _ -> SwaggerItemsArray (map Inline ys)
399+ _ -> OpenApiItemsArray (map Inline ys)
325 ys = map go (V.toList xs)
401 ys = map go (V.toList xs)
326 allSame = and ((zipWith (==)) ys (tail ys))
402 allSame = and ((zipWith (==)) ys (tail ys))
@@ -329,64 +405,178 @@ sketchSchema = sketch . toJSON
329 (z:_) | allSame -> Just z
405 (z:_) | allSame -> Just z
330 _ -> Nothing
406 _ -> Nothing
331 go (Object o) = mempty
407 go (Object o) = mempty
332− & type_ ?~ SwaggerObject
408+ & type_ ?~ OpenApiObject
333− & required .~ HashMap.keys o
409+ & required .~ sort (objectKeys o)
334− & properties .~ fmap (Inline . go) (InsOrdHashMap.fromHashMap o)
410+ & properties .~ fmap (Inline . go) (toInsOrdHashMap o)
336-- | Make a restrictive sketch of a @'Schema'@ based on a @'ToJSON'@ instance.
412-- | Make a restrictive sketch of a @'Schema'@ based on a @'ToJSON'@ instance.
337-- Produced schema uses as much constraints as possible.
413-- Produced schema uses as much constraints as possible.
339−-- >>> BSL.putStrLn $ encode $ sketchStrictSchema "hello"
415+-- >>> BSL.putStrLn $ encodePretty $ sketchStrictSchema "hello"
340−-- {"maxLength":5,"pattern":"hello","minLength":5,"type":"string","enum":["hello"]}
416+-- {
422+-- "pattern": "hello",
342−-- >>> BSL.putStrLn $ encode $ sketchStrictSchema (1, 2, 3)
426+-- >>> BSL.putStrLn $ encodePretty $ sketchStrictSchema (1, 2, 3)
343−-- {"minItems":3,"uniqueItems":true,"items":[{"maximum":1,"minimum":1,"multipleOf":1,"type":"number","enum":[1]},{"maximum":2,"minimum":2,"multipleOf":2,"type":"number","enum":[2]},{"maximum":3,"minimum":3,"multipleOf":3,"type":"number","enum":[3]}],"maxItems":3,"type":"array","enum":[[1,2,3]]}
427+-- {
467+-- "uniqueItems": true
345−-- >>> BSL.putStrLn $ encode $ sketchStrictSchema ("Jack", 25)
470+-- >>> BSL.putStrLn $ encodePretty $ sketchStrictSchema ("Jack", 25)
346−-- {"minItems":2,"uniqueItems":true,"items":[{"maxLength":4,"pattern":"Jack","minLength":4,"type":"string","enum":["Jack"]},{"maximum":25,"minimum":25,"multipleOf":25,"type":"number","enum":[25]}],"maxItems":2,"type":"array","enum":[["Jack",25]]}
471+-- {
485+-- "pattern": "Jack",
501+-- "uniqueItems": true
348-- >>> data Person = Person { name :: String, age :: Int } deriving (Generic)
504-- >>> data Person = Person { name :: String, age :: Int } deriving (Generic)
349-- >>> instance ToJSON Person
505-- >>> instance ToJSON Person
350−-- >>> BSL.putStrLn $ encode $ sketchStrictSchema (Person "Jack" 25)
506+-- >>> BSL.putStrLn $ encodePretty $ sketchStrictSchema (Person "Jack" 25)
351−-- {"minProperties":2,"required":["age","name"],"maxProperties":2,"type":"object","enum":[{"age":25,"name":"Jack"}],"properties":{"age":{"maximum":25,"minimum":25,"multipleOf":25,"type":"number","enum":[25]},"name":{"maxLength":4,"pattern":"Jack","minLength":4,"type":"string","enum":["Jack"]}}}
507+-- {
514+-- "maxProperties": 2,
515+-- "minProperties": 2,
532+-- "pattern": "Jack",
352sketchStrictSchema :: ToJSON a => a -> Schema
542sketchStrictSchema :: ToJSON a => a -> Schema
353sketchStrictSchema = go . toJSON
543sketchStrictSchema = go . toJSON
355− go Null = mempty & type_ ?~ SwaggerNull
545+ go Null = mempty & type_ ?~ OpenApiNull
356 go js@(Bool _) = mempty
546 go js@(Bool _) = mempty
357− & type_ ?~ SwaggerBoolean
547+ & type_ ?~ OpenApiBoolean
358 & enum_ ?~ [js]
548 & enum_ ?~ [js]
359 go js@(String s) = mempty
549 go js@(String s) = mempty
360− & type_ ?~ SwaggerString
550+ & type_ ?~ OpenApiString
361 & maxLength ?~ fromIntegral (T.length s)
551 & maxLength ?~ fromIntegral (T.length s)
362 & minLength ?~ fromIntegral (T.length s)
552 & minLength ?~ fromIntegral (T.length s)
363 & pattern ?~ s
553 & pattern ?~ s
364 & enum_ ?~ [js]
554 & enum_ ?~ [js]
365 go js@(Number n) = mempty
555 go js@(Number n) = mempty
366− & type_ ?~ SwaggerNumber
556+ & type_ ?~ OpenApiNumber
367 & maximum_ ?~ n
557 & maximum_ ?~ n
368 & minimum_ ?~ n
558 & minimum_ ?~ n
369 & multipleOf ?~ n
559 & multipleOf ?~ n
370 & enum_ ?~ [js]
560 & enum_ ?~ [js]
371 go js@(Array xs) = mempty
561 go js@(Array xs) = mempty
372− & type_ ?~ SwaggerArray
562+ & type_ ?~ OpenApiArray
373 & maxItems ?~ fromIntegral sz
563 & maxItems ?~ fromIntegral sz
374 & minItems ?~ fromIntegral sz
564 & minItems ?~ fromIntegral sz
375− & items ?~ SwaggerItemsArray (map (Inline . go) (V.toList xs))
565+ & items ?~ OpenApiItemsArray (map (Inline . go) (V.toList xs))
376 & uniqueItems ?~ allUnique
566 & uniqueItems ?~ allUnique
377 & enum_ ?~ [js]
567 & enum_ ?~ [js]
379 sz = length xs
569 sz = length xs
380 allUnique = sz == HashSet.size (HashSet.fromList (V.toList xs))
570 allUnique = sz == HashSet.size (HashSet.fromList (V.toList xs))
381 go js@(Object o) = mempty
571 go js@(Object o) = mempty
382− & type_ ?~ SwaggerObject
572+ & type_ ?~ OpenApiObject
383− & required .~ names
573+ & required .~ sort names
384− & properties .~ fmap (Inline . go) (InsOrdHashMap.fromHashMap o)
574+ & properties .~ fmap (Inline . go) (toInsOrdHashMap o)
385 & maxProperties ?~ fromIntegral (length names)
575 & maxProperties ?~ fromIntegral (length names)
386 & minProperties ?~ fromIntegral (length names)
576 & minProperties ?~ fromIntegral (length names)
387 & enum_ ?~ [js]
577 & enum_ ?~ [js]
389− names = HashMap.keys o
579+ names = objectKeys o
391class GToSchema (f :: * -> *) where
581class GToSchema (f :: * -> *) where
392 gdeclareNamedSchema :: SchemaOptions -> Proxy f -> Schema -> Declare (Definitions Schema) NamedSchema
582 gdeclareNamedSchema :: SchemaOptions -> Proxy f -> Schema -> Declare (Definitions Schema) NamedSchema
@@ -395,8 +585,8 @@ instance {-# OVERLAPPABLE #-} ToSchema a => ToSchema [a] where
395 declareNamedSchema _ = do
585 declareNamedSchema _ = do
396 ref <- declareSchemaRef (Proxy :: Proxy a)
586 ref <- declareSchemaRef (Proxy :: Proxy a)
397 return $ unnamed $ mempty
587 return $ unnamed $ mempty
398− & type_ ?~ SwaggerArray
588+ & type_ ?~ OpenApiArray
399− & items ?~ SwaggerItemsObject ref
589+ & items ?~ OpenApiItemsObject ref
401instance {-# OVERLAPPING #-} ToSchema String where declareNamedSchema = plain . paramSchemaToSchema
591instance {-# OVERLAPPING #-} ToSchema String where declareNamedSchema = plain . paramSchemaToSchema
402instance ToSchema Bool where declareNamedSchema = plain . paramSchemaToSchema
592instance ToSchema Bool where declareNamedSchema = plain . paramSchemaToSchema
@@ -421,7 +611,7 @@ instance ToSchema Scientific where declareNamedSchema = plain . paramSchemaToSc
421instance ToSchema Double where declareNamedSchema = plain . paramSchemaToSchema
611instance ToSchema Double where declareNamedSchema = plain . paramSchemaToSchema
422instance ToSchema Float where declareNamedSchema = plain . paramSchemaToSchema
612instance ToSchema Float where declareNamedSchema = plain . paramSchemaToSchema
424−instance HasResolution a => ToSchema (Fixed a) where declareNamedSchema = plain . paramSchemaToSchema
614+instance (Typeable (Fixed a), HasResolution a) => ToSchema (Fixed a) where declareNamedSchema = plain . paramSchemaToSchema
426instance ToSchema a => ToSchema (Maybe a) where
616instance ToSchema a => ToSchema (Maybe a) where
427 declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy a)
617 declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy a)
@@ -438,16 +628,22 @@ instance ToSchema UUID.UUID where
438 declareNamedSchema p = pure $ named "UUID" $ paramSchemaToSchema p
628 declareNamedSchema p = pure $ named "UUID" $ paramSchemaToSchema p
439 & example ?~ toJSON (UUID.toText UUID.nil)
629 & example ?~ toJSON (UUID.toText UUID.nil)
441−instance (ToSchema a, ToSchema b) => ToSchema (a, b)
631+instance (ToSchema a, ToSchema b) => ToSchema (a, b) where
632+ declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions
442−instance (ToSchema a, ToSchema b, ToSchema c) => ToSchema (a, b, c)
633+instance (ToSchema a, ToSchema b, ToSchema c) => ToSchema (a, b, c) where
634+ declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions
443−instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d) => ToSchema (a, b, c, d)
635+instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d) => ToSchema (a, b, c, d) where
636+ declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions
444−instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e) => ToSchema (a, b, c, d, e)
637+instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e) => ToSchema (a, b, c, d, e) where
638+ declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions
445−instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f) => ToSchema (a, b, c, d, e, f)
639+instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f) => ToSchema (a, b, c, d, e, f) where
640+ declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions
446−instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f, ToSchema g) => ToSchema (a, b, c, d, e, f, g)
641+instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f, ToSchema g) => ToSchema (a, b, c, d, e, f, g) where
642+ declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions
448timeSchema :: T.Text -> Schema
644timeSchema :: T.Text -> Schema
449timeSchema fmt = mempty
645timeSchema fmt = mempty
450− & type_ ?~ SwaggerString
646+ & type_ ?~ OpenApiString
451 & format ?~ fmt
647 & format ?~ fmt
453-- | Format @"date"@ corresponds to @yyyy-mm-dd@ format.
649-- | Format @"date"@ corresponds to @yyyy-mm-dd@ format.
@@ -462,7 +658,7 @@ instance ToSchema LocalTime where
462 declareNamedSchema _ = pure $ named "LocalTime" $ timeSchema "yyyy-mm-ddThh:MM:ss"
658 declareNamedSchema _ = pure $ named "LocalTime" $ timeSchema "yyyy-mm-ddThh:MM:ss"
463 & example ?~ toJSON (LocalTime (fromGregorian 2016 7 22) (TimeOfDay 7 40 0))
659 & example ?~ toJSON (LocalTime (fromGregorian 2016 7 22) (TimeOfDay 7 40 0))
465−-- | Format @"date"@ corresponds to @yyyy-mm-ddThh:MM:ss(Z|+hh:MM)@ format.
661+-- | Format @"date-time"@ corresponds to @yyyy-mm-ddThh:MM:ss(Z|+hh:MM)@ format.
466instance ToSchema ZonedTime where
662instance ToSchema ZonedTime where
467 declareNamedSchema _ = pure $ named "ZonedTime" $ timeSchema "date-time"
663 declareNamedSchema _ = pure $ named "ZonedTime" $ timeSchema "date-time"
468 & example ?~ toJSON (ZonedTime (LocalTime (fromGregorian 2016 7 22) (TimeOfDay 7 40 0)) (hoursToTimeZone 3))
664 & example ?~ toJSON (ZonedTime (LocalTime (fromGregorian 2016 7 22) (TimeOfDay 7 40 0)) (hoursToTimeZone 3))
@@ -494,7 +690,7 @@ instance ToSchemaByteStringError BSL.ByteString => ToSchema BSL.ByteString where
494instance ToSchema IntSet where declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy (Set Int))
690instance ToSchema IntSet where declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy (Set Int))
496-- | NOTE: This schema does not account for the uniqueness of keys.
692-- | NOTE: This schema does not account for the uniqueness of keys.
497−instance ToSchema a => ToSchema (IntMap a) where
693+instance (ToSchema a) => ToSchema (IntMap a) where
498 declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy [(Int, a)])
694 declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy [(Int, a)])
500instance (ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (Map k v) where
696instance (ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (Map k v) where
@@ -505,7 +701,7 @@ instance (ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (Map k v) where
505 declareObjectMapSchema = do
701 declareObjectMapSchema = do
506 schema <- declareSchemaRef (Proxy :: Proxy v)
702 schema <- declareSchemaRef (Proxy :: Proxy v)
507 return $ unnamed $ mempty
703 return $ unnamed $ mempty
508− & type_ ?~ SwaggerObject
704+ & type_ ?~ OpenApiObject
509 & additionalProperties ?~ AdditionalPropertiesSchema schema
705 & additionalProperties ?~ AdditionalPropertiesSchema schema
511instance (ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (HashMap k v) where
707instance (ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (HashMap k v) where
@@ -513,7 +709,7 @@ instance (ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (HashMap k v) where
514instance {-# OVERLAPPING #-} ToSchema Object where
710instance {-# OVERLAPPING #-} ToSchema Object where
515 declareNamedSchema _ = pure $ NamedSchema (Just "Object") $ mempty
711 declareNamedSchema _ = pure $ NamedSchema (Just "Object") $ mempty
516− & type_ ?~ SwaggerObject
712+ & type_ ?~ OpenApiObject
517 & description ?~ "Arbitrary JSON object."
713 & description ?~ "Arbitrary JSON object."
518 & additionalProperties ?~ AdditionalPropertiesAllowed True
714 & additionalProperties ?~ AdditionalPropertiesAllowed True
@@ -550,11 +746,15 @@ instance ToSchema a => ToSchema (Identity a) where declareNamedSchema _ = declar
551-- | Default schema for @'Bounded'@, @'Integral'@ types.
747-- | Default schema for @'Bounded'@, @'Integral'@ types.
553−-- >>> BSL.putStrLn $ encode $ toSchemaBoundedIntegral (Proxy :: Proxy Int16)
749+-- >>> BSL.putStrLn $ encodePretty $ toSchemaBoundedIntegral (Proxy :: Proxy Int16)
554−-- {"maximum":32767,"minimum":-32768,"type":"integer"}
751+-- "maximum": 32767,
752+-- "minimum": -32768,
555toSchemaBoundedIntegral :: forall a. (Bounded a, Integral a) => Proxy a -> Schema
755toSchemaBoundedIntegral :: forall a. (Bounded a, Integral a) => Proxy a -> Schema
556toSchemaBoundedIntegral _ = mempty
756toSchemaBoundedIntegral _ = mempty
557− & type_ ?~ SwaggerInteger
757+ & type_ ?~ OpenApiInteger
558 & minimum_ ?~ fromInteger (toInteger (minBound :: a))
758 & minimum_ ?~ fromInteger (toInteger (minBound :: a))
559 & maximum_ ?~ fromInteger (toInteger (maxBound :: a))
759 & maximum_ ?~ fromInteger (toInteger (maxBound :: a))
@@ -583,8 +783,27 @@ genericDeclareNamedSchemaNewtype opts f proxy = genericNameSchema opts proxy <$>
583-- >>> instance ToSchema ButtonState
783-- >>> instance ToSchema ButtonState
584-- >>> instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (T.pack . show)
784-- >>> instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (T.pack . show)
585-- >>> type ImageUrl = T.Text
785-- >>> type ImageUrl = T.Text
586−-- >>> BSL.putStrLn $ encode $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))
786+-- >>> BSL.putStrLn $ encodePretty $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))
587−-- {"type":"object","properties":{"Focus":{"type":"string"},"Disabled":{"type":"string"},"Active":{"type":"string"},"Neutral":{"type":"string"},"Hover":{"type":"string"}}}
787+-- {
589-- Note: this is only useful when @key@ is encoded with 'ToJSONKeyText'.
808-- Note: this is only useful when @key@ is encoded with 'ToJSONKeyText'.
590-- If it is encoded with 'ToJSONKeyValue' then a regular schema for @[(key, value)]@ is used.
809-- If it is encoded with 'ToJSONKeyValue' then a regular schema for @[(key, value)]@ is used.
@@ -592,15 +811,15 @@ declareSchemaBoundedEnumKeyMapping :: forall map key value.
592 (Bounded key, Enum key, ToJSONKey key, ToSchema key, ToSchema value)
811 (Bounded key, Enum key, ToJSONKey key, ToSchema key, ToSchema value)
593 => Proxy (map key value) -> Declare (Definitions Schema) Schema
812 => Proxy (map key value) -> Declare (Definitions Schema) Schema
594declareSchemaBoundedEnumKeyMapping _ = case toJSONKey :: ToJSONKeyFunction key of
813declareSchemaBoundedEnumKeyMapping _ = case toJSONKey :: ToJSONKeyFunction key of
595− ToJSONKeyText keyToText _ -> objectSchema keyToText
814+ ToJSONKeyText getKey _ -> objectSchema getKey
596 ToJSONKeyValue _ _ -> declareSchema (Proxy :: Proxy [(key, value)])
815 ToJSONKeyValue _ _ -> declareSchema (Proxy :: Proxy [(key, value)])
598− objectSchema keyToText = do
817+ objectSchema getKey = do
599 valueRef <- declareSchemaRef (Proxy :: Proxy value)
818 valueRef <- declareSchemaRef (Proxy :: Proxy value)
600 let allKeys = [minBound..maxBound :: key]
819 let allKeys = [minBound..maxBound :: key]
601− mkPair k = (keyToText k, valueRef)
820+ mkPair k = (keyToText $ getKey k, valueRef)
602 return $ mempty
821 return $ mempty
603− & type_ ?~ SwaggerObject
822+ & type_ ?~ OpenApiObject
604 & properties .~ InsOrdHashMap.fromList (map mkPair allKeys)
823 & properties .~ InsOrdHashMap.fromList (map mkPair allKeys)
606-- | A 'Schema' for a mapping with 'Bounded' 'Enum' keys.
825-- | A 'Schema' for a mapping with 'Bounded' 'Enum' keys.
@@ -611,8 +830,27 @@ declareSchemaBoundedEnumKeyMapping _ = case toJSONKey :: ToJSONKeyFunction key o
611-- >>> instance ToSchema ButtonState
830-- >>> instance ToSchema ButtonState
612-- >>> instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (T.pack . show)
831-- >>> instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (T.pack . show)
613-- >>> type ImageUrl = T.Text
832-- >>> type ImageUrl = T.Text
614−-- >>> BSL.putStrLn $ encode $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))
833+-- >>> BSL.putStrLn $ encodePretty $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))
615−-- {"type":"object","properties":{"Focus":{"type":"string"},"Disabled":{"type":"string"},"Active":{"type":"string"},"Neutral":{"type":"string"},"Hover":{"type":"string"}}}
834+-- {
617-- Note: this is only useful when @key@ is encoded with 'ToJSONKeyText'.
855-- Note: this is only useful when @key@ is encoded with 'ToJSONKeyText'.
618-- If it is encoded with 'ToJSONKeyValue' then a regular schema for @[(key, value)]@ is used.
856-- If it is encoded with 'ToJSONKeyValue' then a regular schema for @[(key, value)]@ is used.
@@ -622,7 +860,7 @@ toSchemaBoundedEnumKeyMapping :: forall map key value.
622toSchemaBoundedEnumKeyMapping = flip evalDeclare mempty . declareSchemaBoundedEnumKeyMapping
860toSchemaBoundedEnumKeyMapping = flip evalDeclare mempty . declareSchemaBoundedEnumKeyMapping
624-- | A configurable generic @'Schema'@ creator.
862-- | A configurable generic @'Schema'@ creator.
625−genericDeclareSchema :: (Generic a, GToSchema (Rep a)) =>
863+genericDeclareSchema :: (Generic a, GToSchema (Rep a), Typeable a) =>
626 SchemaOptions -> Proxy a -> Declare (Definitions Schema) Schema
864 SchemaOptions -> Proxy a -> Declare (Definitions Schema) Schema
627genericDeclareSchema opts proxy = _namedSchemaSchema <$> genericDeclareNamedSchema opts proxy
865genericDeclareSchema opts proxy = _namedSchemaSchema <$> genericDeclareNamedSchema opts proxy
@@ -630,9 +868,24 @@ genericDeclareSchema opts proxy = _namedSchemaSchema <$> genericDeclareNamedSche
630-- This function applied to @'defaultSchemaOptions'@
868-- This function applied to @'defaultSchemaOptions'@
631-- is used as the default for @'declareNamedSchema'@
869-- is used as the default for @'declareNamedSchema'@
632-- when the type is an instance of @'Generic'@.
870-- when the type is an instance of @'Generic'@.
872+-- Default implementation will use the name from 'Typeable' instance, including concrete
873+-- instantioations of type variables.
877+-- >>> _namedSchemaName $ undeclare $ genericDeclareNamedSchema defaultSchemaOptions (Proxy :: Proxy (Either Int Bool))
878+-- Just "Either_Int_Bool"
633−genericDeclareNamedSchema :: forall a. (Generic a, GToSchema (Rep a)) =>
879+genericDeclareNamedSchema :: forall a. (Generic a, GToSchema (Rep a), Typeable a) =>
634 SchemaOptions -> Proxy a -> Declare (Definitions Schema) NamedSchema
880 SchemaOptions -> Proxy a -> Declare (Definitions Schema) NamedSchema
881+genericDeclareNamedSchema opts _ =
635−genericDeclareNamedSchema opts _ = gdeclareNamedSchema opts (Proxy :: Proxy (Rep a)) mempty
882+ rename (Just $ T.pack name) <$> gdeclareNamedSchema opts (Proxy :: Proxy (Rep a)) mempty
886+ orig = fmap unspace $ show $ typeRep @a
887+ name = datatypeNameModifier opts orig
637-- | Derive a 'Generic'-based name for a datatype and assign it to a given 'Schema'.
890-- | Derive a 'Generic'-based name for a datatype and assign it to a given 'Schema'.
638genericNameSchema :: forall a d f.
891genericNameSchema :: forall a d f.
@@ -659,8 +912,8 @@ paramSchemaToSchema = toParamSchema
660nullarySchema :: Schema
913nullarySchema :: Schema
661nullarySchema = mempty
914nullarySchema = mempty
662− & type_ ?~ SwaggerArray
915+ & type_ ?~ OpenApiArray
663− & items ?~ SwaggerItemsArray []
916+ & items ?~ OpenApiItemsArray []
665gtoNamedSchema :: GToSchema f => SchemaOptions -> Proxy f -> NamedSchema
918gtoNamedSchema :: GToSchema f => SchemaOptions -> Proxy f -> NamedSchema
666gtoNamedSchema opts proxy = undeclare $ gdeclareNamedSchema opts proxy mempty
919gtoNamedSchema opts proxy = undeclare $ gdeclareNamedSchema opts proxy mempty
@@ -690,12 +943,15 @@ instance (Selector s, GToSchema f, GToSchema (S1 s f)) => GToSchema (C1 c (S1 s
690 | unwrapUnaryRecords opts = fieldSchema
943 | unwrapUnaryRecords opts = fieldSchema
691 | otherwise =
944 | otherwise =
692 case schema ^. items of
945 case schema ^. items of
693− Just (SwaggerItemsArray [_]) -> fieldSchema
946+ Just (OpenApiItemsArray [_]) -> fieldSchema
695− declare defs
948+ -- We have to run recordSchema instead of just using its defs,
949+ -- since those can be recursive and will lead to infinite loop,
950+ -- see https://github.com/biocad/openapi3/pull/37
951+ NamedSchema _ schema' <- recordSchema
696− return (unnamed schema)
952+ return (unnamed schema')
698− (defs, NamedSchema _ schema) = runDeclare recordSchema mempty
954+ (_, NamedSchema _ schema) = runDeclare recordSchema mempty
699 recordSchema = gdeclareNamedSchema opts (Proxy :: Proxy (S1 s f)) s
955 recordSchema = gdeclareNamedSchema opts (Proxy :: Proxy (S1 s f)) s
700 fieldSchema = gdeclareNamedSchema opts (Proxy :: Proxy f) s
956 fieldSchema = gdeclareNamedSchema opts (Proxy :: Proxy f) s
@@ -718,10 +974,10 @@ gdeclareSchemaRef opts proxy = do
718 return $ Ref (Reference name)
974 return $ Ref (Reference name)
719 _ -> Inline <$> gdeclareSchema opts proxy
975 _ -> Inline <$> gdeclareSchema opts proxy
721−appendItem :: Referenced Schema -> Maybe SwaggerItems -> Maybe SwaggerItems
977+appendItem :: Referenced Schema -> Maybe OpenApiItems -> Maybe OpenApiItems
722−appendItem x Nothing = Just (SwaggerItemsArray [x])
978+appendItem x Nothing = Just (OpenApiItemsArray [x])
723−appendItem x (Just (SwaggerItemsArray xs)) = Just (SwaggerItemsArray (xs ++ [x]))
979+appendItem x (Just (OpenApiItemsArray xs)) = Just (OpenApiItemsArray (xs ++ [x]))
724−appendItem _ _ = error "GToSchema.appendItem: cannot append to SwaggerItemsObject"
980+appendItem _ _ = error "GToSchema.appendItem: cannot append to OpenApiItemsObject"
726withFieldSchema :: forall proxy s f. (Selector s, GToSchema f) =>
982withFieldSchema :: forall proxy s f. (Selector s, GToSchema f) =>
727 SchemaOptions -> proxy s f -> Bool -> Schema -> Declare (Definitions Schema) Schema
983 SchemaOptions -> proxy s f -> Bool -> Schema -> Declare (Definitions Schema) Schema
@@ -730,12 +986,12 @@ withFieldSchema opts _ isRequiredField schema = do
731 if T.null fname
987 if T.null fname
732 then schema
988 then schema
733− & type_ ?~ SwaggerArray
989+ & type_ ?~ OpenApiArray
734 & items %~ appendItem ref
990 & items %~ appendItem ref
735 & maxItems %~ Just . maybe 1 (+1) -- increment maxItems
991 & maxItems %~ Just . maybe 1 (+1) -- increment maxItems
736 & minItems %~ Just . maybe 1 (+1) -- increment minItems
992 & minItems %~ Just . maybe 1 (+1) -- increment minItems
737 else schema
993 else schema
738− & type_ ?~ SwaggerObject
994+ & type_ ?~ OpenApiObject
739 & properties . at fname ?~ ref
995 & properties . at fname ?~ ref
740 & if isRequiredField
996 & if isRequiredField
741 then required %~ (++ [fname])
997 then required %~ (++ [fname])
@@ -770,14 +1026,14 @@ gdeclareNamedSumSchema opts proxy _
770 | otherwise = do
1026 | otherwise = do
771 (schemas, _) <- runWriterT declareSumSchema
1027 (schemas, _) <- runWriterT declareSumSchema
772 return $ unnamed $ mempty
1028 return $ unnamed $ mempty
773− & type_ ?~ SwaggerObject
1029+ & type_ ?~ OpenApiObject
774 & oneOf ?~ (snd <$> schemas)
1030 & oneOf ?~ (snd <$> schemas)
776 declareSumSchema = gsumToSchema opts proxy
1032 declareSumSchema = gsumToSchema opts proxy
777 (sumSchemas, All allNullary) = undeclare (runWriterT declareSumSchema)
1033 (sumSchemas, All allNullary) = undeclare (runWriterT declareSumSchema)
779 toStringTag schemas = mempty
1035 toStringTag schemas = mempty
780− & type_ ?~ SwaggerString
1036+ & type_ ?~ OpenApiString
781 & enum_ ?~ map (String . fst) sumSchemas
1037 & enum_ ?~ map (String . fst) sumSchemas
783type AllNullary = All
1039type AllNullary = All
@@ -799,15 +1055,15 @@ gsumConToSchemaWith ref opts _ = (tag, schema)
799 case ref of
1055 case ref of
800 -- If subschema is an object and constructor is a record, we add tag directly
1056 -- If subschema is an object and constructor is a record, we add tag directly
801 -- to the record, as Aeson does it.
1057 -- to the record, as Aeson does it.
802− Just (Inline sub) | sub ^. type_ == Just SwaggerObject && isRecord -> Inline $ sub
1058+ Just (Inline sub) | sub ^. type_ == Just OpenApiObject && isRecord -> Inline $ sub
803 & required <>~ [T.pack tagField]
1059 & required <>~ [T.pack tagField]
804− & properties . at (T.pack tagField) ?~ (Inline $ mempty & type_ ?~ SwaggerString & enum_ ?~ [String tag])
1060+ & properties . at (T.pack tagField) ?~ (Inline $ mempty & type_ ?~ OpenApiString & enum_ ?~ [String tag])
806 -- If it is not a record, we need to put subschema into "contents" field.
1062 -- If it is not a record, we need to put subschema into "contents" field.
807 _ | not isRecord -> Inline $ mempty
1063 _ | not isRecord -> Inline $ mempty
808− & type_ ?~ SwaggerObject
1064+ & type_ ?~ OpenApiObject
809 & required .~ [T.pack tagField]
1065 & required .~ [T.pack tagField]
810− & properties . at (T.pack tagField) ?~ (Inline $ mempty & type_ ?~ SwaggerString & enum_ ?~ [String tag])
1066+ & properties . at (T.pack tagField) ?~ (Inline $ mempty & type_ ?~ OpenApiString & enum_ ?~ [String tag])
811 -- If constructor is nullary, there is no content.
1067 -- If constructor is nullary, there is no content.
812 & case ref of
1068 & case ref of
813 Just r -> (properties . at (T.pack contentsField) ?~ r) . (required <>~ [T.pack contentsField])
1069 Just r -> (properties . at (T.pack contentsField) ?~ r) . (required <>~ [T.pack contentsField])
@@ -815,17 +1071,17 @@ gsumConToSchemaWith ref opts _ = (tag, schema)
816 -- In the remaining cases we combine "tag" object and "contents" object using allOf.
1072 -- In the remaining cases we combine "tag" object and "contents" object using allOf.
817 _ -> Inline $ mempty
1073 _ -> Inline $ mempty
818− & type_ ?~ SwaggerObject
1074+ & type_ ?~ OpenApiObject
819 & allOf ?~ [Inline $ mempty
1075 & allOf ?~ [Inline $ mempty
820− & type_ ?~ SwaggerObject
1076+ & type_ ?~ OpenApiObject
821 & required .~ (T.pack tagField : if isRecord then [] else [T.pack contentsField])
1077 & required .~ (T.pack tagField : if isRecord then [] else [T.pack contentsField])
822− & properties . at (T.pack tagField) ?~ (Inline $ mempty & type_ ?~ SwaggerString & enum_ ?~ [String tag])]
1078+ & properties . at (T.pack tagField) ?~ (Inline $ mempty & type_ ?~ OpenApiString & enum_ ?~ [String tag])]
823 & if isRecord
1079 & if isRecord
824 then allOf . _Just <>~ [refOrNullary]
1080 then allOf . _Just <>~ [refOrNullary]
825− else allOf . _Just <>~ [Inline $ mempty & type_ ?~ SwaggerObject & properties . at (T.pack contentsField) ?~ refOrNullary]
1081+ else allOf . _Just <>~ [Inline $ mempty & type_ ?~ OpenApiObject & properties . at (T.pack contentsField) ?~ refOrNullary]
826 UntaggedValue -> refOrEnum -- Aeson encodes nullary constructors as strings in this case.
1082 UntaggedValue -> refOrEnum -- Aeson encodes nullary constructors as strings in this case.
827 ObjectWithSingleField -> Inline $ mempty
1083 ObjectWithSingleField -> Inline $ mempty
828− & type_ ?~ SwaggerObject
1084+ & type_ ?~ OpenApiObject
829 & required .~ [tag]
1085 & required .~ [tag]
830 & properties . at tag ?~ refOrNullary
1086 & properties . at tag ?~ refOrNullary
831 TwoElemArray -> error "unrepresentable in OpenAPI 3"
1087 TwoElemArray -> error "unrepresentable in OpenAPI 3"
@@ -833,7 +1089,7 @@ gsumConToSchemaWith ref opts _ = (tag, schema)
833 tag = T.pack (constructorTagModifier opts (conName (Proxy3 :: Proxy3 c f p)))
1089 tag = T.pack (constructorTagModifier opts (conName (Proxy3 :: Proxy3 c f p)))
834 isRecord = conIsRecord (Proxy3 :: Proxy3 c f p)
1090 isRecord = conIsRecord (Proxy3 :: Proxy3 c f p)
835 refOrNullary = fromMaybe (Inline nullarySchema) ref
1091 refOrNullary = fromMaybe (Inline nullarySchema) ref
836− refOrEnum = fromMaybe (Inline $ mempty & type_ ?~ SwaggerString & enum_ ?~ [String tag]) ref
1092+ refOrEnum = fromMaybe (Inline $ mempty & type_ ?~ OpenApiString & enum_ ?~ [String tag]) ref
838gsumConToSchema :: (GToSchema (C1 c f), Constructor c) =>
1094gsumConToSchema :: (GToSchema (C1 c f), Constructor c) =>
839 SchemaOptions -> Proxy (C1 c f) -> Declare (Definitions Schema) [(T.Text, Referenced Schema)]
1095 SchemaOptions -> Proxy (C1 c f) -> Declare (Definitions Schema) [(T.Text, Referenced Schema)]
@@ -858,7 +1114,13 @@ data Proxy2 a b = Proxy2
859data Proxy3 a b c = Proxy3
1115data Proxy3 a b c = Proxy3
861−-- $setup
1117+{- $setup
862−-- >>> import Data.OpenApi
1118+>>> import Data.OpenApi
863−-- >>> import Data.Aeson (encode)
1119+>>> import Data.Aeson (encode)
864−-- >>> import Data.Aeson.Types (toJSONKeyText)
1120+>>> import Data.Aeson.Types (toJSONKeyText)
1121+>>> import Data.OpenApi.Internal.Utils
1122+>>> :set -XScopedTypeVariables
1123+>>> :set -XDeriveAnyClass
1124+>>> :set -XStandaloneDeriving
1125+>>> :set -XTypeApplications