From 2631a1a08c1ba17cafa8f31673d47a95231e3e31 Mon Sep 17 00:00:00 2001 From: Wolfgang Schuster Date: Thu, 21 Nov 2024 13:50:33 -0600 Subject: [PATCH 1/5] Support for application/x-www-form-urlencoded bodies --- src/OpenApi/Generate.elm | 103 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 8 deletions(-) diff --git a/src/OpenApi/Generate.elm b/src/OpenApi/Generate.elm index 8d3220e7..db12f93f 100644 --- a/src/OpenApi/Generate.elm +++ b/src/OpenApi/Generate.elm @@ -15,6 +15,7 @@ import Elm.Annotation import Elm.Arg import Elm.Case import Elm.Declare +import Elm.Let import Elm.Op import FastDict import FastSet @@ -37,6 +38,7 @@ import Gen.OpenApi.Common import Gen.Result import Gen.String import Gen.Task +import Gen.Url import Gen.Url.Builder import Json.Decode import Json.Schema.Definitions @@ -70,6 +72,7 @@ type ContentSchema = EmptyContent | JsonContent Common.Type | StringContent Mime + | UrlEncodedContent Common.Type | BytesContent Mime @@ -624,7 +627,8 @@ toRequestFunctions server effectTypes method pathUrl operation = let encoded : Elm.Expression encoded = - encoder <| Elm.get "body" config + Elm.get "body" config + |> encoder in { core = Gen.Http.jsonBody encoded , elmPages = Gen.BackendTask.Http.jsonBody encoded @@ -632,6 +636,47 @@ toRequestFunctions server effectTypes method pathUrl operation = } ) + UrlEncodedContent type_ -> + SchemaUtils.typeToEncoder True type_ + |> CliMonad.map + (\encoder config -> + let + encoded : Elm.Expression + encoded = + Elm.get "body" config + |> encoder + |> Gen.Json.Decode.decodeValue (Gen.Json.Decode.dict Gen.Json.Decode.value) + |> Gen.Result.map + (\keyValues -> + keyValues + |> Gen.Dict.toList + |> Gen.List.call_.map + (Elm.fn ( "keyVal", Nothing ) + (\keyVal -> + Elm.Let.letIn + (\( key, value ) -> + Gen.String.call_.concat + (Elm.list + [ Gen.Url.call_.percentEncode key + , Elm.string "=" + , Gen.Url.call_.percentEncode (Gen.Json.Encode.encode 0 value) + ] + ) + ) + |> Elm.Let.tuple "key" "value" keyVal + |> Elm.Let.toExpression + ) + ) + |> Gen.String.call_.join (Elm.string "&") + ) + |> Gen.Result.withDefault (Elm.string "") + in + { core = Gen.Http.call_.stringBody (Elm.string "application/x-www-form-urlencoded") encoded + , elmPages = Gen.BackendTask.Http.jsonBody encoded + , lamderaProgramTest = Gen.Effect.Http.jsonBody encoded + } + ) + StringContent mime -> CliMonad.succeed <| \config -> @@ -668,6 +713,10 @@ toRequestFunctions server effectTypes method pathUrl operation = SchemaUtils.typeToAnnotationWithNullable True type_ |> CliMonad.map (\annotation -> [ ( Common.UnsafeName "body", annotation ) ]) + UrlEncodedContent type_ -> + SchemaUtils.typeToAnnotationWithNullable True type_ + |> CliMonad.map (\annotation -> [ ( Common.UnsafeName "body", annotation ) ]) + StringContent _ -> CliMonad.succeed [ ( Common.UnsafeName "body", Elm.Annotation.string ) ] @@ -1806,13 +1855,22 @@ contentToContentSchema qualify content = stringContent "text/plain" htmlSchema Nothing -> - let - msg : String - msg = - "The content doesn't have an application/json, text/html or text/plain option, it has " ++ String.join ", " (Dict.keys content) - in - fallback - |> Maybe.withDefault (CliMonad.fail msg) + case Dict.get "application/x-www-form-urlencoded" content of + Just urlEncodedSchema -> + CliMonad.succeed urlEncodedSchema + |> CliMonad.stepOrFail "The request's application/x-www-form-urlencoded content option doesn't havea schema" + (OpenApi.MediaType.schema >> Maybe.map OpenApi.Schema.get) + |> CliMonad.andThen (SchemaUtils.schemaToType qualify) + |> CliMonad.map (\{ type_ } -> UrlEncodedContent type_) + + Nothing -> + let + msg : String + msg = + "The content doesn't have an application/json, text/html, text/plain, or application/x-www-form-urlencoded option, it has " ++ String.join ", " (Dict.keys content) + in + fallback + |> Maybe.withDefault (CliMonad.fail msg) stringContent : String -> OpenApi.MediaType.MediaType -> CliMonad ContentSchema stringContent mime htmlSchema = @@ -1854,6 +1912,8 @@ contentToContentSchema qualify content = else if singleKey == "application/octet-stream" then CliMonad.succeed (BytesContent singleKey) + -- else if singleKey == "application/x-www-form-urlencoded" then + -- CliMonad.succeed (StringContent singleKey) else default (Just fallback) @@ -2491,6 +2551,10 @@ operationToTypesExpectAndResolver functionName operation = SchemaUtils.typeToDecoder True type_ |> CliMonad.andThen common + UrlEncodedContent type_ -> + SchemaUtils.typeToDecoder True type_ + |> CliMonad.andThen common + StringContent _ -> CliMonad.succeed Gen.Json.Decode.string |> CliMonad.andThen common @@ -2551,6 +2615,11 @@ operationToTypesExpectAndResolver functionName operation = (SchemaUtils.typeToAnnotationWithNullable False type_) (SchemaUtils.typeToAnnotationWithNullable True type_) + UrlEncodedContent type_ -> + CliMonad.map2 Tuple.pair + (SchemaUtils.typeToAnnotationWithNullable False type_) + (SchemaUtils.typeToAnnotationWithNullable True type_) + StringContent _ -> CliMonad.succeed ( Elm.Annotation.string @@ -2647,6 +2716,24 @@ operationToTypesExpectAndResolver functionName operation = errorDecoders errorTypeDeclaration + UrlEncodedContent type_ -> + CliMonad.map3 + (\successDecoder errorDecoders_ ( errorTypeDeclaration_, errorTypeAnnotation ) -> + { successType = type_ + , bodyTypeAnnotation = Elm.Annotation.string + , errorTypeDeclaration = errorTypeDeclaration_ + , errorTypeAnnotation = errorTypeAnnotation + , expect = expectJsonBetter errorDecoders_ successDecoder + , resolver = + { core = Gen.OpenApi.Common.jsonResolverCustom errorDecoders_ successDecoder + , lamderaProgramTest = Gen.OpenApi.Common.jsonResolverCustomEffect errorDecoders_ successDecoder + } + } + ) + (SchemaUtils.typeToDecoder True type_) + errorDecoders + errorTypeDeclaration + StringContent _ -> CliMonad.map2 (\errorDecoders_ ( errorTypeDeclaration_, errorTypeAnnotation ) -> From fee9d709ef063c02bdffec291916e3d8a0df89cf Mon Sep 17 00:00:00 2001 From: Wolfgang Schuster Date: Mon, 3 Mar 2025 18:25:45 -0600 Subject: [PATCH 2/5] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c501457f..4394d746 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support for params being passed in the header - Support for `type : null` - Support for `const : ` +- Support for `application/x-www-form-urlencoded` bodies - [Support for `additionalProperties` in objects](https://github.com/wolfadex/elm-open-api-cli/pull/184). [Adam DiCarlo](https://github.com/adamdicarlo0) ## [0.7.0] - 2024-09-23 From 509af00981f6b608448d445d1a845d41073cadc8 Mon Sep 17 00:00:00 2001 From: Wolfgang Schuster Date: Thu, 21 Nov 2024 13:53:20 -0600 Subject: [PATCH 3/5] Remove unused code --- src/OpenApi/Generate.elm | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/OpenApi/Generate.elm b/src/OpenApi/Generate.elm index db12f93f..35db350d 100644 --- a/src/OpenApi/Generate.elm +++ b/src/OpenApi/Generate.elm @@ -1912,8 +1912,6 @@ contentToContentSchema qualify content = else if singleKey == "application/octet-stream" then CliMonad.succeed (BytesContent singleKey) - -- else if singleKey == "application/x-www-form-urlencoded" then - -- CliMonad.succeed (StringContent singleKey) else default (Just fallback) From e7f64e229a3258d4d9af3f0f23a746f19c3d2e6d Mon Sep 17 00:00:00 2001 From: Wolfgang Schuster Date: Mon, 3 Mar 2025 18:31:04 -0600 Subject: [PATCH 4/5] Fix typo --- src/OpenApi/Generate.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenApi/Generate.elm b/src/OpenApi/Generate.elm index 35db350d..e499c6d0 100644 --- a/src/OpenApi/Generate.elm +++ b/src/OpenApi/Generate.elm @@ -1858,7 +1858,7 @@ contentToContentSchema qualify content = case Dict.get "application/x-www-form-urlencoded" content of Just urlEncodedSchema -> CliMonad.succeed urlEncodedSchema - |> CliMonad.stepOrFail "The request's application/x-www-form-urlencoded content option doesn't havea schema" + |> CliMonad.stepOrFail "The request's application/x-www-form-urlencoded content option doesn't have a schema" (OpenApi.MediaType.schema >> Maybe.map OpenApi.Schema.get) |> CliMonad.andThen (SchemaUtils.schemaToType qualify) |> CliMonad.map (\{ type_ } -> UrlEncodedContent type_) From c822be3cf2945c09b9b091a83515ce5c901d8a8e Mon Sep 17 00:00:00 2001 From: Wolfgang Schuster Date: Mon, 3 Mar 2025 18:51:30 -0600 Subject: [PATCH 5/5] Use the correct encoder for non-core http --- src/OpenApi/Generate.elm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenApi/Generate.elm b/src/OpenApi/Generate.elm index e499c6d0..cdd19f9b 100644 --- a/src/OpenApi/Generate.elm +++ b/src/OpenApi/Generate.elm @@ -672,8 +672,8 @@ toRequestFunctions server effectTypes method pathUrl operation = |> Gen.Result.withDefault (Elm.string "") in { core = Gen.Http.call_.stringBody (Elm.string "application/x-www-form-urlencoded") encoded - , elmPages = Gen.BackendTask.Http.jsonBody encoded - , lamderaProgramTest = Gen.Effect.Http.jsonBody encoded + , elmPages = Gen.Http.call_.stringBody (Elm.string "application/x-www-form-urlencoded") encoded + , lamderaProgramTest = Gen.Http.call_.stringBody (Elm.string "application/x-www-form-urlencoded") encoded } )