diff --git a/autodocodec-api-usage/test/Autodocodec/Aeson/SchemaSpec.hs b/autodocodec-api-usage/test/Autodocodec/Aeson/SchemaSpec.hs index bbf8fb5..0cb22c4 100644 --- a/autodocodec-api-usage/test/Autodocodec/Aeson/SchemaSpec.hs +++ b/autodocodec-api-usage/test/Autodocodec/Aeson/SchemaSpec.hs @@ -56,6 +56,7 @@ spec = do jsonSchemaSpec @(Either Bool Text) "either-bool-text" jsonSchemaSpec @(Either (Either Bool Scientific) Text) "either-either-bool-scientific-text" jsonSchemaSpec @[Text] "list-text" + jsonSchemaSpec @(NonEmpty Text) "nonempty-text" jsonSchemaSpec @Example "example" jsonSchemaSpec @Recursive "recursive" jsonSchemaSpec @Via "via" diff --git a/autodocodec-api-usage/test/Autodocodec/AesonSpec.hs b/autodocodec-api-usage/test/Autodocodec/AesonSpec.hs index b9f0f92..0ebb8be 100644 --- a/autodocodec-api-usage/test/Autodocodec/AesonSpec.hs +++ b/autodocodec-api-usage/test/Autodocodec/AesonSpec.hs @@ -17,6 +17,7 @@ import Data.GenValidity.Aeson () import Data.GenValidity.Scientific () import Data.GenValidity.Text () import Data.Int +import Data.List.NonEmpty (NonEmpty) import Data.Scientific import Data.Text (Text) import qualified Data.Text.Lazy as LT @@ -51,6 +52,7 @@ spec = do aesonCodecSpec @(Either Bool Text) aesonCodecSpec @(Either (Either Bool Scientific) Text) aesonCodecSpec @[Text] + aesonCodecSpec @(NonEmpty Text) aesonCodecSpec @Fruit aesonCodecSpec @Example aesonCodecSpec @Recursive diff --git a/autodocodec-api-usage/test/Autodocodec/OpenAPISpec.hs b/autodocodec-api-usage/test/Autodocodec/OpenAPISpec.hs index cbc9e8a..d3d05e9 100644 --- a/autodocodec-api-usage/test/Autodocodec/OpenAPISpec.hs +++ b/autodocodec-api-usage/test/Autodocodec/OpenAPISpec.hs @@ -18,6 +18,7 @@ import Data.GenValidity.Containers () import Data.GenValidity.Scientific () import Data.GenValidity.Text () import Data.Int +import Data.List.NonEmpty (NonEmpty) import Data.Maybe import Data.OpenApi (Components (..), OpenApi (..)) import qualified Data.OpenApi as OpenAPI @@ -57,6 +58,7 @@ spec = do openAPISchemaSpec @(Either Bool Text) "either-bool-text" openAPISchemaSpec @(Either (Either Bool Scientific) Text) "either-either-bool-scientific-text" openAPISchemaSpec @[Text] "list-text" + openAPISchemaSpec @(NonEmpty Text) "nonempty-text" openAPISchemaSpec @Fruit "fruit" openAPISchemaSpec @Example "example" openAPISchemaSpec @Recursive "recursive" diff --git a/autodocodec-api-usage/test/Autodocodec/ShowSpec.hs b/autodocodec-api-usage/test/Autodocodec/ShowSpec.hs index 6da11a2..da6a924 100644 --- a/autodocodec-api-usage/test/Autodocodec/ShowSpec.hs +++ b/autodocodec-api-usage/test/Autodocodec/ShowSpec.hs @@ -14,6 +14,7 @@ import Data.GenValidity.Aeson () import Data.GenValidity.Scientific () import Data.GenValidity.Text () import Data.Int +import Data.List.NonEmpty (NonEmpty) import Data.Scientific import Data.Text (Text) import qualified Data.Text.Lazy as LT @@ -47,6 +48,7 @@ spec = do showCodecSpec @(Either Bool Text) "either-bool-text" showCodecSpec @(Either (Either Bool Scientific) Text) "either-either-bool-scientific-text" showCodecSpec @[Text] "list-text" + showCodecSpec @(NonEmpty Text) "nonempty-text" showCodecSpec @Fruit "fruit" showCodecSpec @Example "example" showCodecSpec @Recursive "recursive" diff --git a/autodocodec-api-usage/test/Autodocodec/SwaggerSpec.hs b/autodocodec-api-usage/test/Autodocodec/SwaggerSpec.hs index 3747513..a5eac97 100644 --- a/autodocodec-api-usage/test/Autodocodec/SwaggerSpec.hs +++ b/autodocodec-api-usage/test/Autodocodec/SwaggerSpec.hs @@ -18,6 +18,7 @@ import Data.GenValidity.Containers () import Data.GenValidity.Scientific () import Data.GenValidity.Text () import Data.Int +import Data.List.NonEmpty (NonEmpty) import Data.Maybe import Data.Scientific import Data.Swagger (Swagger (..)) @@ -57,6 +58,7 @@ spec = do swaggerSchemaSpec @(Either Bool Text) "either-bool-text" swaggerSchemaSpec @(Either (Either Bool Scientific) Text) "either-either-bool-scientific-text" swaggerSchemaSpec @[Text] "list-text" + swaggerSchemaSpec @(NonEmpty Text) "nonempty-text" swaggerSchemaSpec @Fruit "fruit" swaggerSchemaSpec @Example "example" swaggerSchemaSpec @Recursive "recursive" diff --git a/autodocodec-api-usage/test/Autodocodec/Yaml/DocumentSpec.hs b/autodocodec-api-usage/test/Autodocodec/Yaml/DocumentSpec.hs index 2659f16..c3ea39e 100644 --- a/autodocodec-api-usage/test/Autodocodec/Yaml/DocumentSpec.hs +++ b/autodocodec-api-usage/test/Autodocodec/Yaml/DocumentSpec.hs @@ -15,6 +15,7 @@ import Data.GenValidity.Aeson () import Data.GenValidity.Scientific () import Data.GenValidity.Text () import Data.Int +import Data.List.NonEmpty (NonEmpty) import Data.Scientific import Data.Text (Text) import qualified Data.Text.Lazy as LT @@ -48,6 +49,7 @@ spec = do yamlSchemaSpec @(Either Bool Text) "either-bool-text" yamlSchemaSpec @(Either (Either Bool Scientific) Text) "either-either-bool-scientific-text" yamlSchemaSpec @[Text] "list-text" + yamlSchemaSpec @(NonEmpty Text) "nonempty-text" yamlSchemaSpec @Fruit "fruit" yamlSchemaSpec @Example "example" yamlSchemaSpec @Recursive "recursive" diff --git a/autodocodec-api-usage/test_resources/json-schema/nonempty-text.json b/autodocodec-api-usage/test_resources/json-schema/nonempty-text.json new file mode 100644 index 0000000..a5d186e --- /dev/null +++ b/autodocodec-api-usage/test_resources/json-schema/nonempty-text.json @@ -0,0 +1,6 @@ +{ + "items": { + "type": "string" + }, + "type": "array" +} \ No newline at end of file diff --git a/autodocodec-api-usage/test_resources/openapi-schema/nonempty-text.json b/autodocodec-api-usage/test_resources/openapi-schema/nonempty-text.json new file mode 100644 index 0000000..1177e51 --- /dev/null +++ b/autodocodec-api-usage/test_resources/openapi-schema/nonempty-text.json @@ -0,0 +1,18 @@ +{ + "components": { + "schemas": { + "(NonEmpty Text)": { + "items": { + "type": "string" + }, + "type": "array" + } + } + }, + "openapi": "3.0.0", + "info": { + "version": "", + "title": "" + }, + "paths": {} +} \ No newline at end of file diff --git a/autodocodec-api-usage/test_resources/show-codec/nonempty-text.txt b/autodocodec-api-usage/test_resources/show-codec/nonempty-text.txt new file mode 100644 index 0000000..0d7a074 --- /dev/null +++ b/autodocodec-api-usage/test_resources/show-codec/nonempty-text.txt @@ -0,0 +1 @@ +MapCodec _ _ (MapCodec _ _ (ArrayOfCodec Nothing (StringCodec Nothing))) \ No newline at end of file diff --git a/autodocodec-api-usage/test_resources/swagger-schema/nonempty-text.json b/autodocodec-api-usage/test_resources/swagger-schema/nonempty-text.json new file mode 100644 index 0000000..1054c50 --- /dev/null +++ b/autodocodec-api-usage/test_resources/swagger-schema/nonempty-text.json @@ -0,0 +1,15 @@ +{ + "swagger": "2.0", + "info": { + "version": "", + "title": "" + }, + "definitions": { + "(NonEmpty Text)": { + "items": { + "type": "string" + }, + "type": "array" + } + } +} \ No newline at end of file diff --git a/autodocodec-api-usage/test_resources/yaml-schema/nonempty-text.txt b/autodocodec-api-usage/test_resources/yaml-schema/nonempty-text.txt new file mode 100644 index 0000000..296888a --- /dev/null +++ b/autodocodec-api-usage/test_resources/yaml-schema/nonempty-text.txt @@ -0,0 +1 @@ +-  diff --git a/autodocodec/src/Autodocodec/Class.hs b/autodocodec/src/Autodocodec/Class.hs index a9d4dfb..831cad3 100644 --- a/autodocodec/src/Autodocodec/Class.hs +++ b/autodocodec/src/Autodocodec/Class.hs @@ -9,6 +9,8 @@ module Autodocodec.Class where import Autodocodec.Codec import qualified Data.Aeson as JSON import Data.Int +import Data.List.NonEmpty (NonEmpty (..)) +import qualified Data.List.NonEmpty as NE import Data.Scientific import Data.Text (Text) import qualified Data.Text.Lazy as LT @@ -100,6 +102,13 @@ instance (HasCodec l, HasCodec r) => HasCodec (Either l r) where instance HasCodec a => HasCodec [a] where codec = listCodecForStringCompatibility +instance HasCodec a => HasCodec (NonEmpty a) where + codec = bimapCodec parseNonEmptyList NE.toList codec + where + parseNonEmptyList l = case NE.nonEmpty l of + Nothing -> Left "Expected a nonempty list, but got an empty list." + Just ne -> Right ne + -- | A required field -- -- During decoding, the field must be in the object.