Compare commits

...

4 Commits

Author SHA1 Message Date
dependabot[bot]
61b07ad802 Bump fsharp-analyzers from 0.25.0 to 0.26.0 (#134)
* Bump fsharp-analyzers from 0.25.0 to 0.26.0

Bumps [fsharp-analyzers](https://github.com/ionide/FSharp.Analyzers.SDK) from 0.25.0 to 0.26.0.
- [Release notes](https://github.com/ionide/FSharp.Analyzers.SDK/releases)
- [Changelog](https://github.com/ionide/FSharp.Analyzers.SDK/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ionide/FSharp.Analyzers.SDK/compare/v0.25.0...v0.26.0)

---
updated-dependencies:
- dependency-name: fsharp-analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-05-20 19:02:54 +00:00
dependabot[bot]
59369bcb94 Bump cachix/install-nix-action from 26 to 27 (#133) 2024-05-20 12:47:58 +01:00
dependabot[bot]
072169e4e3 Bump ApiSurface from 4.0.36 to 4.0.39 (#132)
* Bump ApiSurface from 4.0.36 to 4.0.39

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.0.36 to 4.0.39.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.0.36...ApiSurface.4.0.39)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-05-06 13:59:29 +01:00
Patrick Stevens
91136a25ab Enable query params in Get request endpoint (#131) 2024-04-30 19:03:20 +00:00
12 changed files with 132 additions and 20 deletions

View File

@@ -9,7 +9,7 @@
] ]
}, },
"fsharp-analyzers": { "fsharp-analyzers": {
"version": "0.25.0", "version": "0.26.0",
"commands": [ "commands": [
"fsharp-analyzers" "fsharp-analyzers"
] ]

View File

@@ -28,7 +28,7 @@ jobs:
with: with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -49,7 +49,7 @@ jobs:
with: with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -66,7 +66,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -79,7 +79,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -92,7 +92,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -105,7 +105,7 @@ jobs:
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@master
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -118,7 +118,7 @@ jobs:
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@master
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -132,7 +132,7 @@ jobs:
with: with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -188,7 +188,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v26 uses: cachix/install-nix-action@V27
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}

View File

@@ -288,7 +288,52 @@ module PureGymApi =
| v -> v), | v -> v),
System.Uri ( System.Uri (
("/v2/gymSessions/member" ("/v2/gymSessions/member"
+ "?fromDate=" + (if "/v2/gymSessions/member".IndexOf (char 63) > 0 then
"&"
else
"?")
+ "fromDate="
+ ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)
+ "&toDate="
+ ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)),
System.UriKind.Relative
)
)
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = uri
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! responseStream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
let! jsonNode =
System.Text.Json.Nodes.JsonNode.ParseAsync (responseStream, cancellationToken = ct)
|> Async.AwaitTask
return Sessions.jsonParse jsonNode
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetSessionsWithQuery (fromDate : DateOnly, toDate : DateOnly, ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let uri =
System.Uri (
(match client.BaseAddress with
| null -> System.Uri "https://whatnot.com"
| v -> v),
System.Uri (
("/v2/gymSessions/member?foo=1"
+ (if "/v2/gymSessions/member?foo=1".IndexOf (char 63) > 0 then
"&"
else
"?")
+ "fromDate="
+ ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode) + ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)
+ "&toDate=" + "&toDate="
+ ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)), + ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)),

View File

@@ -38,6 +38,10 @@ type IPureGymApi =
abstract GetSessions : abstract GetSessions :
[<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions> [<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions>
[<Get "/v2/gymSessions/member?foo=1">]
abstract GetSessionsWithQuery :
[<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions>
// An example from RestEase's own docs // An example from RestEase's own docs
[<Post "users/new">] [<Post "users/new">]
abstract CreateUserString : [<Body>] user : string * ?ct : CancellationToken -> Task<string> abstract CreateUserString : [<Body>] user : string * ?ct : CancellationToken -> Task<string>

View File

@@ -12,7 +12,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ApiSurface" Version="4.0.36" /> <PackageReference Include="ApiSurface" Version="4.0.39" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/>
<PackageReference Include="NUnit" Version="4.1.0"/> <PackageReference Include="NUnit" Version="4.1.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>

View File

@@ -234,6 +234,33 @@ module TestPureGymRestApi =
api.GetSessions(startDate, endDate).Result |> shouldEqual expected api.GetSessions(startDate, endDate).Result |> shouldEqual expected
[<TestCaseSource(nameof sessionsCases)>]
let ``Test GetSessionsWithQuery``
(baseUri : Uri, (startDate : DateOnly, (endDate : DateOnly, (json : string, expected : Sessions))))
=
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
async {
message.Method |> shouldEqual HttpMethod.Get
// This one is specified as being absolute, in its attribute on the IPureGymApi type
let expectedUri =
let fromDate = dateOnlyToString startDate
let toDate = dateOnlyToString endDate
$"https://example.com/v2/gymSessions/member?foo=1&fromDate=%s{fromDate}&toDate=%s{toDate}"
message.RequestUri.ToString () |> shouldEqual expectedUri
let content = new StringContent (json)
let resp = new HttpResponseMessage (HttpStatusCode.OK)
resp.Content <- content
return resp
}
use client = HttpClientMock.make baseUri proc
let api = PureGymApi.make client
api.GetSessionsWithQuery(startDate, endDate).Result |> shouldEqual expected
[<Test>] [<Test>]
let ``URI example`` () = let ``URI example`` () =
let proc (message : HttpRequestMessage) : HttpResponseMessage Async = let proc (message : HttpRequestMessage) : HttpResponseMessage Async =

View File

@@ -33,7 +33,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ApiSurface" Version="4.0.36"/> <PackageReference Include="ApiSurface" Version="4.0.39"/>
<PackageReference Include="FsCheck" Version="2.16.6"/> <PackageReference Include="FsCheck" Version="2.16.6"/>
<PackageReference Include="FsUnit" Version="6.0.0"/> <PackageReference Include="FsUnit" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/>

View File

@@ -308,6 +308,27 @@ module internal HttpClientGenerator =
| None -> failwith "Unable to get parameter variable name from anonymous parameter" | None -> failwith "Unable to get parameter variable name from anonymous parameter"
| Some id -> id | Some id -> id
let urlSeparator =
// apparent Myriad bug: `IndexOf '?'` gets formatted as `IndexOf ?` which is clearly wrong
let questionMark =
SynExpr.CreateParen (
SynExpr.CreateApp (
SynExpr.CreateIdentString "char",
SynExpr.CreateConst (SynConst.Int32 63)
)
)
let containsQuestion =
info.UrlTemplate
|> SynExpr.callMethodArg "IndexOf" questionMark
|> SynExpr.greaterThanOrEqual (SynExpr.CreateConst (SynConst.Int32 0))
SynExpr.ifThenElse
containsQuestion
(SynExpr.CreateConst (SynConst.CreateString "?"))
(SynExpr.CreateConst (SynConst.CreateString "&"))
|> SynExpr.CreateParen
let prefix = let prefix =
SynExpr.CreateIdent firstValueId SynExpr.CreateIdent firstValueId
|> SynExpr.toString firstValue.Type |> SynExpr.toString firstValue.Type
@@ -316,7 +337,7 @@ module internal HttpClientGenerator =
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]) SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ])
) )
|> SynExpr.CreateParen |> SynExpr.CreateParen
|> SynExpr.plus (SynExpr.CreateConstString ("?" + firstKey + "=")) |> SynExpr.plus (SynExpr.plus urlSeparator (SynExpr.CreateConstString (firstKey + "=")))
(prefix, queryParams) (prefix, queryParams)
||> List.fold (fun uri (paramKey, paramValue) -> ||> List.fold (fun uri (paramKey, paramValue) ->

View File

@@ -311,3 +311,19 @@ module internal SynExpr =
), ),
x x
) )
/// {y} >= {x}
let greaterThanOrEqual (x : SynExpr) (y : SynExpr) : SynExpr =
SynExpr.CreateApp (
SynExpr.CreateAppInfix (
SynExpr.CreateLongIdent (
SynLongIdent.SynLongIdent (
[ Ident.Create "op_GreaterThanOrEqual" ],
[],
[ Some (IdentTrivia.OriginalNotation ">=") ]
)
),
y
),
x
)

View File

@@ -10,7 +10,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.9.3]" /> <PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.10.0]" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -7,7 +7,6 @@
}; };
outputs = { outputs = {
self,
nixpkgs, nixpkgs,
flake-utils, flake-utils,
... ...

View File

@@ -3,8 +3,8 @@
{fetchNuGet}: [ {fetchNuGet}: [
(fetchNuGet { (fetchNuGet {
pname = "fsharp-analyzers"; pname = "fsharp-analyzers";
version = "0.25.0"; version = "0.26.0";
sha256 = "sha256-njfJYi40jNvrD+mgu9LtQw2Omh8P1SSDThesozH0KQY="; sha256 = "sha256-60Bl36LOb/zVNdH2SBSuQ5O41lP9dKTNZbs5vvYs+3U=";
}) })
(fetchNuGet { (fetchNuGet {
pname = "fantomas"; pname = "fantomas";
@@ -13,8 +13,8 @@
}) })
(fetchNuGet { (fetchNuGet {
pname = "ApiSurface"; pname = "ApiSurface";
version = "4.0.36"; version = "4.0.39";
sha256 = "sha256-xqIkMvjJD5UaAHYw8B0CU4h+fJvxNSVspMFro2dz0Rc="; sha256 = "sha256-I4K5nJbltsfL/1r+KPTIo2wUd30zsCC2pkrnIRnsRHM=";
}) })
(fetchNuGet { (fetchNuGet {
pname = "Fantomas.Core"; pname = "Fantomas.Core";