Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
pull_request:
branches:
- master
- net5

jobs:
build:
Expand Down
13 changes: 8 additions & 5 deletions paket.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ version 5.198.0
source https://api.nuget.org/v3/index.json
frameworks: net5.0, netstandard2.0

nuget FSharp.Core 4.3.4
nuget FSharp.Core 4.7.0
nuget System.Net.Http
nuget Newtonsoft.Json
nuget System.Text.Json
nuget FSharp.SystemTextJson
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need 3 explicitly referenced packages here?

 nuget System.Net.Http.Json
 nuget System.Text.Json
 nuget FSharp.SystemTextJson

can we reference only FSharp.SystemTextJson?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that we will use JSON extensions to HttpClient and HttpResponseMessage

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we can

nuget Microsoft.OpenApi.Readers
nuget NETStandard.Library.NETFramework
nuget Newtonsoft.Json

# delete when we drop custom parser for v2
nuget YamlDotNet
Expand All @@ -27,14 +29,15 @@ group Server
nuget Microsoft.AspNetCore.HttpsPolicy
nuget Swashbuckle.AspNetCore prerelease
nuget Microsoft.OpenApi
nuget FSharp.Core
nuget Microsoft.AspNetCore.Mvc.NewtonsoftJson
nuget FSharp.Core 4.7.0

group Test
source https://api.nuget.org/v3/index.json
frameworks: net5.0

nuget FSharp.Compiler.Service redirects: force
nuget FSharp.Core redirects: force
nuget FSharp.Core 4.7.0 redirects: force

nuget Microsoft.NET.Test.Sdk
nuget Expecto
nuget YoloDev.Expecto.TestSdk
456 changes: 60 additions & 396 deletions paket.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/Common/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("SwaggerProvider")>]
[<assembly: AssemblyProductAttribute("SwaggerProvider")>]
[<assembly: AssemblyDescriptionAttribute("F# Type Provider for Swagger & Open API")>]
[<assembly: AssemblyVersionAttribute("0.13.0")>]
[<assembly: AssemblyFileVersionAttribute("0.13.0")>]
[<assembly: AssemblyVersionAttribute("1.0.0")>]
[<assembly: AssemblyFileVersionAttribute("1.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "SwaggerProvider"
let [<Literal>] AssemblyProduct = "SwaggerProvider"
let [<Literal>] AssemblyDescription = "F# Type Provider for Swagger & Open API"
let [<Literal>] AssemblyVersion = "0.13.0"
let [<Literal>] AssemblyFileVersion = "0.13.0"
let [<Literal>] AssemblyVersion = "1.0.0"
let [<Literal>] AssemblyFileVersion = "1.0.0"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
Expand Down Expand Up @@ -27,7 +27,6 @@
<Paket>True</Paket>
<Link>paket-files/ProvidedTypes.fs</Link>
</Compile>
<Compile Include="..\SwaggerProvider.Runtime\Serialization.fs" />
<Compile Include="..\SwaggerProvider.Runtime\ProvidedApiClientBase.fs">
<Link>ProvidedApiClientBase.fs</Link>
</Compile>
Expand Down
6 changes: 3 additions & 3 deletions src/SwaggerProvider.DesignTime/paket.references
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
File:ProvidedTypes.fsi
File:ProvidedTypes.fs
File: ProvidedTypes.fsi
File: ProvidedTypes.fs
File: Pluralizer.fs
File: NameUtils.fs

FSharp.Core

System.Net.Http
Newtonsoft.Json
System.Text.Json
Microsoft.OpenApi.Readers

YamlDotNet
2 changes: 1 addition & 1 deletion src/SwaggerProvider.DesignTime/v2/DefinitionCompiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ type DefinitionCompiler (schema:SwaggerObject, provideNullable) as this =
| String -> typeof<string>
| Date | DateTime -> typeof<DateTime>
| File -> typeof<byte>.MakeArrayType(1)
| Enum _ -> typeof<string> //NOTE: find better type
| Enum _ -> typeof<int> //NOTE: find better type
| Array eTy ->
(compileSchemaObject ns (ns.ReserveUniqueName tyName "Item") eTy true ns.RegisterType).MakeArrayType(1)
| Dictionary eTy ->
Expand Down
20 changes: 13 additions & 7 deletions src/SwaggerProvider.DesignTime/v2/OperationCompiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ open SwaggerProvider.Internal.v2.Parser.Schema
open Swagger.Internal

open System
open System.Collections.Generic
open System.Net.Http
open System.Text.Json
open System.Text.RegularExpressions

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.ExprShape
open System.Text.RegularExpressions
open System.Net.Http
open System.Collections.Generic
open SwaggerProvider.Internal
open Swagger
open Swagger.Internal
Expand Down Expand Up @@ -254,17 +255,22 @@ type OperationCompiler (schema:SwaggerObject, defCompiler:DefinitionCompiler, ig

[
ProvidedConstructor(
[ProvidedParameter("httpClient", typeof<HttpClient>)],
[ProvidedParameter("httpClient", typeof<HttpClient>);
ProvidedParameter("options", typeof<JsonSerializerOptions>, optionalValue = (null:JsonSerializerOptions))],
invokeCode = (fun args ->
match args with
| [] -> failwith "Generated constructors should always pass the instance as the first argument!"
| _ -> <@@ () @@>),
BaseConstructorCall = fun args -> (baseCtor, args))
ProvidedConstructor([],
ProvidedConstructor(
[ProvidedParameter("options", typeof<JsonSerializerOptions>, optionalValue = (null:JsonSerializerOptions))],
invokeCode = (fun args -> <@@ () @@>),
BaseConstructorCall = fun args ->
let httpClient = <@ RuntimeHelpers.getDefaultHttpClient defaultHost @>
let args' = args @ [httpClient]
let httpClient = <@ RuntimeHelpers.getDefaultHttpClient defaultHost @> :> Expr
let args' =
match args with
| [instance; options] -> [instance; httpClient; options]
| _ -> failwithf "unexpected arguments received %A" args
(baseCtor, args'))
] |> ty.AddMembers

Expand Down
46 changes: 20 additions & 26 deletions src/SwaggerProvider.DesignTime/v2/Parser/SwaggerParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,48 @@ open SwaggerProvider.Internal.v2.Parser.Schema
open SwaggerProvider.Internal.v2.Parser.Exceptions

module internal JsonAdapter =
open Newtonsoft.Json.Linq
open System.Text.Json

/// Schema node for Swagger schemes in Json format
type JsonNodeAdapter(value:JToken) =
type JsonNodeAdapter(value:JsonElement) =
inherit SchemaNode()

override __.AsBoolean() = value.ToObject<bool>()
override __.AsBoolean() = value.GetBoolean()

override __.AsString() = value.ToObject<string>()
override __.AsString() = value.ToString()

override __.AsArray() =
match value.Type with
| JTokenType.Array ->
value :?> JArray
|> Seq.map (fun x -> JsonNodeAdapter(x) :> SchemaNode)
|> Seq.toArray
match value.ValueKind with
| JsonValueKind.Array ->
[|for item in value.EnumerateArray() do JsonNodeAdapter(item) :> SchemaNode|]
| _ -> raise <| UnexpectedValueTypeException(value, "string")

override __.AsStringArrayWithoutNull() =
match value.Type with
| JTokenType.String ->
[|value.ToObject<string>()|]
| JTokenType.Array ->
value :?> JArray
|> Seq.map (fun x -> x.ToObject<string>())
match value.ValueKind with
| JsonValueKind.String ->
[|value.GetString()|]
| JsonValueKind.Array ->
[|for item in value.EnumerateArray() do item.GetString()|]
|> Seq.filter (fun x -> x <> "null")
|> Seq.toArray
| other ->
failwithf "Value: '%A' cannot be converted to StringArray" other

override __.Properties() =
match value.Type with
| JTokenType.Object ->
(value :?> JObject).Properties()
|> Seq.map (fun x -> x.Name, JsonNodeAdapter(x.Value) :> SchemaNode)
|> Seq.toArray
| _ -> raise <| UnexpectedValueTypeException(value, "JObject")
match value.ValueKind with
| JsonValueKind.Object ->
[|for item in value.EnumerateObject() do item.Name, JsonNodeAdapter(item.Value) :> SchemaNode|]
| _ -> raise <| UnexpectedValueTypeException(value, "Object")

override __.TryGetProperty(property) =
match value.Type with
| JTokenType.Object ->
let obj = value :?> JObject
match obj.TryGetValue(property) with
match value.ValueKind with
| JsonValueKind.Object ->
match value.TryGetProperty(property) with
| true, x -> Some(JsonNodeAdapter(x) :> SchemaNode)
| _ -> None
| _ -> None

let parse = JToken.Parse >> JsonNodeAdapter
let parse (string: string) = (JsonDocument.Parse string).RootElement |> JsonNodeAdapter

module internal YamlAdapter =
open System.IO
Expand Down
17 changes: 11 additions & 6 deletions src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ namespace SwaggerProvider.Internal.v3.Compilers

open System
open System.Net.Http
open System.Threading.Tasks
open System.Text.Json
open System.Text.RegularExpressions

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.ExprShape
open Microsoft.OpenApi.Models
open ProviderImplementation.ProvidedTypes
open FSharp.Data.Runtime.NameUtils
open Microsoft.OpenApi.Models

open SwaggerProvider.Internal
open Swagger
Expand Down Expand Up @@ -382,17 +382,22 @@ type OperationCompiler (schema:OpenApiDocument, defCompiler:DefinitionCompiler,

[
ProvidedConstructor(
[ProvidedParameter("httpClient", typeof<HttpClient>)],
[ProvidedParameter("httpClient", typeof<HttpClient>);
ProvidedParameter("options", typeof<JsonSerializerOptions>, optionalValue = (null:JsonSerializerOptions))],
invokeCode = (fun args ->
match args with
| [] -> failwith "Generated constructors should always pass the instance as the first argument!"
| _ -> <@@ () @@>),
BaseConstructorCall = fun args -> (baseCtor, args))
ProvidedConstructor([],
ProvidedConstructor(
[ProvidedParameter("options", typeof<JsonSerializerOptions>, optionalValue = (null:JsonSerializerOptions))],
invokeCode = (fun args -> <@@ () @@>),
BaseConstructorCall = fun args ->
let httpClient = <@ RuntimeHelpers.getDefaultHttpClient defaultHost @>
let args' = args @ [httpClient]
let httpClient = <@ RuntimeHelpers.getDefaultHttpClient defaultHost @> :> Expr
let args' =
match args with
| [instance; options] -> [instance; httpClient; options]
| _ -> failwithf "unexpected arguments received %A" args
(baseCtor, args'))
] |> ty.AddMembers

Expand Down
29 changes: 12 additions & 17 deletions src/SwaggerProvider.Runtime/ProvidedApiClientBase.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,34 @@ namespace Swagger

open System
open System.Net.Http
open Newtonsoft.Json

open Swagger.Serialization
open System.Text.Json
open System.Text.Json.Serialization

type OpenApiException(code:int, description:string) =
inherit Exception(description)
member __.StatusCode = code
member __.Description = description

type ProvidedApiClientBase(httpClient: HttpClient) =
let jsonSerializerSettings =
let settings =
JsonSerializerSettings(
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.None)
type ProvidedApiClientBase(httpClient: HttpClient, options: JsonSerializerOptions) =

#if TP_RUNTIME
[
OptionConverter () :> JsonConverter
ByteArrayConverter () :> JsonConverter
]
|> List.iter settings.Converters.Add
let options =
if isNull options then
let options = JsonSerializerOptions()
options.Converters.Add(JsonFSharpConverter())
options
else options
#endif
settings

member val HttpClient = httpClient with get, set

abstract member Serialize: obj -> string
abstract member Deserialize: string * Type -> obj

default __.Serialize(value:obj): string =
JsonConvert.SerializeObject(value, jsonSerializerSettings)
JsonSerializer.Serialize(value, options)
default __.Deserialize(value, retTy:Type): obj =
JsonConvert.DeserializeObject(value, retTy, jsonSerializerSettings)
JsonSerializer.Deserialize(value, retTy, options)

// This code may change in the future, especially when task{} become part of FSharp.Core.dll
member this.CallAsync(request: HttpRequestMessage, errorCodes:string[], errorDescriptions:string[]) : Async<HttpContent> =
Expand Down
11 changes: 6 additions & 5 deletions src/SwaggerProvider.Runtime/RuntimeHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ namespace Swagger.Internal

open System
open System
open Newtonsoft.Json
open System.Threading.Tasks
open System.Net.Http
open System.Text.Json
open System.Text.Json.Serialization
open System.Threading.Tasks

module MediaTypes =
let [<Literal>] ApplicationJson = "application/json"
Expand Down Expand Up @@ -107,7 +108,7 @@ module RuntimeHelpers =

let getPropertyNameAttribute name =
{ new Reflection.CustomAttributeData() with
member __.Constructor = typeof<JsonPropertyAttribute>.GetConstructor([|typeof<string>|])
member __.Constructor = typeof<JsonPropertyNameAttribute>.GetConstructor([|typeof<string>|])
member __.ConstructorArguments = [|Reflection.CustomAttributeTypedArgument(typeof<string>, name)|] :> Collections.Generic.IList<_>
member __.NamedArguments = [||] :> Collections.Generic.IList<_> }

Expand All @@ -120,8 +121,8 @@ module RuntimeHelpers =
object.GetType().GetProperties(System.Reflection.BindingFlags.Public ||| System.Reflection.BindingFlags.Instance)
|> Seq.choose (fun prop ->
let name =
match prop.GetCustomAttributes(typeof<JsonPropertyAttribute>, false) with
| [|x|] -> (x :?> JsonPropertyAttribute).PropertyName
match prop.GetCustomAttributes(typeof<JsonPropertyNameAttribute>, false) with
| [|x|] -> (x :?> JsonPropertyNameAttribute).Name
| _ -> prop.Name
prop.GetValue(object)
|> Option.ofObj
Expand Down
46 changes: 0 additions & 46 deletions src/SwaggerProvider.Runtime/Serialization.fs

This file was deleted.

Loading