Add HttpClient generator (#12)

This commit is contained in:
Patrick Stevens
2024-10-07 19:44:11 +01:00
committed by GitHub
parent da609db2ce
commit 9b7a27f2de
41 changed files with 7187 additions and 64 deletions

View File

@@ -0,0 +1,16 @@
namespace WoofWare.Whippet.Plugin.HttpClient
/// Attribute indicating a record type to which the "create HTTP client" Whippet
/// generator should apply during build.
/// This generator is intended to replicate much of the functionality of RestEase,
/// i.e. to stamp out HTTP REST clients from interfaces defining the API.
///
/// If you supply isExtensionMethod = false, you will get a genuine module (which can
/// be consumed from C#) rather than extension methods.
type HttpClientAttribute (isExtensionMethod : bool) =
inherit System.Attribute ()
/// The default value of `isExtensionMethod`, the optional argument to the HttpClientAttribute constructor.
static member DefaultIsExtensionMethod = true
/// Shorthand for the "isExtensionMethod = false" constructor; see documentation there for details.
new () = HttpClientAttribute HttpClientAttribute.DefaultIsExtensionMethod

View File

@@ -0,0 +1,6 @@
# WoofWare.Whippet.Plugin.HttpClient.Attributes
This is a very slim runtime dependency which consumers of WoofWare.Whippet.Plugin.HttpClient may optionally take.
This dependency contains attributes which control that source generator,
although you may instead omit this dependency and control the generator entirely through configuration in consumer's `.fsproj`.
Please see WoofWare.Whippet.Plugin.HttpClient's README for further information.

View File

@@ -0,0 +1,88 @@
namespace WoofWare.Whippet.Plugin.HttpClient
open System
/// Module containing duplicates of the supported RestEase attributes, in case you don't want
/// to take a dependency on RestEase.
module RestEase =
/// Indicates that a method represents an HTTP Get query to the specified endpoint.
type GetAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Post query to the specified endpoint.
type PostAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Delete query to the specified endpoint.
type DeleteAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Head query to the specified endpoint.
type HeadAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Options query to the specified endpoint.
type OptionsAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Put query to the specified endpoint.
type PutAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Patch query to the specified endpoint.
type PatchAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Trace query to the specified endpoint.
type TraceAttribute (path : string) =
inherit Attribute ()
/// Indicates that this argument to a method is interpolated into the HTTP request at runtime
/// by setting a query parameter (with the given name) to the value of the annotated argument.
type QueryAttribute (paramName : string) =
inherit Attribute ()
new () = QueryAttribute null
/// Indicates that this interface represents a REST client which accesses an API whose paths are
/// all relative to the given address.
///
/// We will essentially unconditionally append a slash to this for you, on the grounds that you probably don't
/// intend the base path *itself* to be an endpoint.
type BaseAddressAttribute (addr : string) =
inherit Attribute ()
/// Indicates that this interface member causes the interface to set a header with the given name,
/// whose value is obtained whenever required by a fresh call to the interface member.
type HeaderAttribute (header : string, value : string option) =
inherit Attribute ()
new (header : string) = HeaderAttribute (header, None)
new (header : string, value : string) = HeaderAttribute (header, Some value)
/// Indicates that this argument to a method is interpolated into the request path at runtime
/// by writing it into the templated string that specifies the HTTP query e.g. in the `[<Get "/foo/{template}">]`.
type PathAttribute (path : string option) =
inherit Attribute ()
new (path : string) = PathAttribute (Some path)
new () = PathAttribute None
/// Indicates that this argument to a method is passed to the remote API by being serialised into the request
/// body.
type BodyAttribute () =
inherit Attribute ()
/// This is interpolated into every URL, between the BaseAddress and the path specified by e.g. [<Get>].
/// Note that if the [<Get>]-specified path starts with a slash, the BasePath is ignored, because then [<Get>]
/// is considered to be relative to the URL root (i.e. the host part of the BaseAddress).
/// Similarly, if the [<BasePath>] starts with a slash, then any path component of the BaseAddress is ignored.
///
/// We will essentially unconditionally append a slash to this for you, on the grounds that you probably don't
/// intend the base path *itself* to be an endpoint.
///
/// Can contain {placeholders}; hopefully your methods define values for those placeholders with [<Path>]
/// attributes!
type BasePathAttribute (path : string) =
inherit Attribute ()
/// Indicates that this REST endpoint may return a non-success status code but we still want to consume its output.
type AllowAnyStatusCodeAttribute () =
inherit Attribute ()

View File

@@ -0,0 +1,41 @@
WoofWare.Whippet.Plugin.HttpClient.HttpClientAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.HttpClientAttribute..ctor [constructor]: bool
WoofWare.Whippet.Plugin.HttpClient.HttpClientAttribute..ctor [constructor]: unit
WoofWare.Whippet.Plugin.HttpClient.HttpClientAttribute.DefaultIsExtensionMethod [static property]: [read-only] bool
WoofWare.Whippet.Plugin.HttpClient.HttpClientAttribute.get_DefaultIsExtensionMethod [static method]: unit -> bool
WoofWare.Whippet.Plugin.HttpClient.RestEase inherit obj
WoofWare.Whippet.Plugin.HttpClient.RestEase+AllowAnyStatusCodeAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+AllowAnyStatusCodeAttribute..ctor [constructor]: unit
WoofWare.Whippet.Plugin.HttpClient.RestEase+BaseAddressAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+BaseAddressAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+BasePathAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+BasePathAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+BodyAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+BodyAttribute..ctor [constructor]: unit
WoofWare.Whippet.Plugin.HttpClient.RestEase+DeleteAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+DeleteAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+GetAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+GetAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+HeadAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+HeadAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+HeaderAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+HeaderAttribute..ctor [constructor]: (string, string option)
WoofWare.Whippet.Plugin.HttpClient.RestEase+HeaderAttribute..ctor [constructor]: (string, string)
WoofWare.Whippet.Plugin.HttpClient.RestEase+HeaderAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+OptionsAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+OptionsAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+PatchAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+PatchAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+PathAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+PathAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+PathAttribute..ctor [constructor]: string option
WoofWare.Whippet.Plugin.HttpClient.RestEase+PathAttribute..ctor [constructor]: unit
WoofWare.Whippet.Plugin.HttpClient.RestEase+PostAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+PostAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+PutAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+PutAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+QueryAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+QueryAttribute..ctor [constructor]: string
WoofWare.Whippet.Plugin.HttpClient.RestEase+QueryAttribute..ctor [constructor]: unit
WoofWare.Whippet.Plugin.HttpClient.RestEase+TraceAttribute inherit System.Attribute
WoofWare.Whippet.Plugin.HttpClient.RestEase+TraceAttribute..ctor [constructor]: string

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="Attributes.fs" />
<Compile Include="RestEase.fs" />
<EmbeddedResource Include="SurfaceBaseline.txt" />
<EmbeddedResource Include="version.json" />
<Content Include="README.md" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="4.3.4" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,11 @@
{
"version": "0.1",
"publicReleaseRefSpec": [
"^refs/heads/main$"
],
"pathFilters": [
"./",
":/global.json",
":/Directory.Build.props"
]
}