Start generating parse methods #4

Merged
patrick merged 12 commits from visits into main 2023-12-28 21:08:09 +00:00
17 changed files with 756 additions and 94 deletions
Showing only changes of commit 5fd1a52bd8 - Show all commits

View File

@@ -5,8 +5,8 @@ open PureGym
type AuthArg = type AuthArg =
| [<Unique ; CustomAppSettings "PUREGYM_BEARER_TOKEN">] Bearer_Token of string | [<Unique ; CustomAppSettings "PUREGYM_BEARER_TOKEN">] Bearer_Token of string
| [<Unique>] User_Email of string | [<Unique ; EqualsAssignmentOrSpaced>] User_Email of string
| [<Unique>] Pin of string | [<Unique ; EqualsAssignmentOrSpaced>] Pin of string
| [<GatherUnrecognized>] Others of string | [<GatherUnrecognized>] Others of string
interface IArgParserTemplate with interface IArgParserTemplate with

View File

@@ -14,7 +14,7 @@ type GetTokenArg =
match s with match s with
| GetTokenArg.Pin _ -> "Eight-digit PureGym user's PIN" | GetTokenArg.Pin _ -> "Eight-digit PureGym user's PIN"
| GetTokenArg.User_Email _ -> "PureGym user's email address" | GetTokenArg.User_Email _ -> "PureGym user's email address"
| GetTokenArg.StdIn _ -> "Read anything not specified on the command line from stdin" | GetTokenArg.StdIn -> "Read anything not specified on the command line from stdin"
static member Parse (args : ParseResults<GetTokenArg>) : Result<UsernamePin, ArguParseException> = static member Parse (args : ParseResults<GetTokenArg>) : Result<UsernamePin, ArguParseException> =
let canUseStdin = args.TryGetResult(GetTokenArg.StdIn).IsSome let canUseStdin = args.TryGetResult(GetTokenArg.StdIn).IsSome

View File

@@ -48,9 +48,10 @@ module Fullness =
let run (args : FullnessArgs) = let run (args : FullnessArgs) =
task { task {
let! client = Api.make args.Creds let! client = Dto.make args.Creds
let! id = GymSelector.canonicalId client args.Gym let! id = GymSelector.canonicalId client args.Gym
let! attendance = client.GetGymAttendance id let! attendance = client.GetGymAttendance id
let attendance = failwith ""
if args.Terse then if args.Terse then
System.Console.WriteLine attendance.TotalPeopleInGym System.Console.WriteLine attendance.TotalPeopleInGym

View File

@@ -44,7 +44,7 @@ module LookupGym =
let run (args : LookupGymArgs) = let run (args : LookupGymArgs) =
task { task {
let! client = Api.make args.Creds let! client = Dto.make args.Creds
let! s = client.GetGym 19 let! s = client.GetGym 19
System.Console.WriteLine (string<Gym> s) System.Console.WriteLine (string<Gym> s)
return 0 return 0

View File

@@ -31,9 +31,8 @@ module MemberActivity =
let run (args : MemberActivityArgs) = let run (args : MemberActivityArgs) =
task { task {
let! client = Api.make args.Creds let! client = Dto.make args.Creds
let! activity = client.GetMemberActivity () let! activity = client.GetMemberActivity ()
let activity = activity.ToMemberActivity ()
System.Console.WriteLine (string<MemberActivityThisMonth> activity) System.Console.WriteLine (string<MemberActivityThisMonth> activity)
return 0 return 0
} }

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -41,7 +41,7 @@ module Sessions =
let run (args : SessionsArgs) = let run (args : SessionsArgs) =
task { task {
let! client = Api.make args.Creds let! client = Dto.make args.Creds
let! activity = client.GetSessions args.FromDate args.ToDate let! activity = client.GetSessions args.FromDate args.ToDate
System.Console.WriteLine (string<Sessions> activity) System.Console.WriteLine (string<Sessions> activity)

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject> <IsTestProject>true</IsTestProject>
@@ -9,12 +9,15 @@
<ItemGroup> <ItemGroup>
<Compile Include="TestSurface.fs" /> <Compile Include="TestSurface.fs" />
<Compile Include="TestJson.fs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ApiSurface" Version="4.0.12" /> <PackageReference Include="ApiSurface" Version="4.0.12" />
<PackageReference Include="FsCheck" Version="2.16.6" />
<PackageReference Include="FsUnit" Version="5.6.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="NUnit" Version="3.13.3"/> <PackageReference Include="NUnit" Version="3.14.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2"/> <PackageReference Include="NUnit3TestAdapter" Version="4.4.2"/>
<PackageReference Include="NUnit.Analyzers" Version="3.6.1"/> <PackageReference Include="NUnit.Analyzers" Version="3.6.1"/>
<PackageReference Include="coverlet.collector" Version="3.2.0"/> <PackageReference Include="coverlet.collector" Version="3.2.0"/>

273
PureGym.Test/TestJson.fs Normal file
View File

@@ -0,0 +1,273 @@
namespace PureGym.Test
open System
open System.Text.Json.Nodes
open NUnit.Framework
open FsUnitTyped
open PureGym
[<TestFixture>]
module TestJson =
let gymOpeningHoursCases =
[
"""{"openingHours": [], "isAlwaysOpen": false}""", { GymOpeningHours.OpeningHours = [] ; IsAlwaysOpen = false }
"""{"openingHours": ["something"], "isAlwaysOpen": false}""", { GymOpeningHours.OpeningHours = ["something"] ; IsAlwaysOpen = false }
]
|> List.map TestCaseData
[<TestCaseSource (nameof(gymOpeningHoursCases))>]
let ``GymOpeningHours JSON parse`` (json : string, expected : GymOpeningHours) =
JsonNode.Parse json
|> GymOpeningHours.jsonParse
|> shouldEqual expected
let gymAccessOptionsCases =
List.allPairs [ true ; false ] [ true ; false ]
|> List.map (fun (a, b) ->
let s = sprintf """{"pinAccess": %b, "qrCodeAccess": %b}""" a b
s, { GymAccessOptions.PinAccess = a ; QrCodeAccess = b }
)
|> List.map TestCaseData
[<TestCaseSource (nameof(gymAccessOptionsCases))>]
let ``GymAccessOptions JSON parse`` (json : string, expected : GymAccessOptions) =
JsonNode.Parse json
|> GymAccessOptions.jsonParse
|> shouldEqual expected
let gymLocationCases =
[
"""{"latitude": 1.0, "longitude": 3.0}""", { GymLocation.Latitude = 1.0 ; Longitude = 3.0 }
]
|> List.map TestCaseData
[<TestCaseSource (nameof(gymLocationCases))>]
let ``GymLocation JSON parse`` (json : string, expected : GymLocation) =
JsonNode.Parse json
|> GymLocation.jsonParse
|> shouldEqual expected
let gymAddressCases =
[
"""{"addressLine1": "", "postCode": "hi", "town": ""}""", { GymAddress.AddressLine1 = "" ; AddressLine2 = None ; AddressLine3 = None ; County = None ; Postcode = "hi" ; Town = "" }
"""{"addressLine1": "", "addressLine2": null, "postCode": "hi", "town": ""}""", { GymAddress.AddressLine1 = "" ; AddressLine2 = None ; AddressLine3 = None ; County = None ; Postcode = "hi" ; Town = "" }
]
|> List.map TestCaseData
[<TestCaseSource (nameof(gymAddressCases))>]
let ``GymAddress JSON parse`` (json : string, expected : GymAddress) =
JsonNode.Parse (json, Nullable (JsonNodeOptions(PropertyNameCaseInsensitive = true)))
|> GymAddress.jsonParse
|> shouldEqual expected
let gymCases =
let ovalJson = """{"name":"London Oval","id":19,"status":2,"address":{"addressLine1":"Canterbury Court","addressLine2":"Units 4, 4A, 5 And 5A","addressLine3":"Kennington Park","town":"LONDON","county":null,"postcode":"SW9 6DE"},"phoneNumber":"+44 3444770005","emailAddress":"info.londonoval@puregym.com","staffMembers":null,"gymOpeningHours":{"isAlwaysOpen":true,"openingHours":[]},"reasonsToJoin":null,"accessOptions":{"pinAccess":true,"qrCodeAccess":true},"virtualTourUrl":null,"personalTrainersUrl":null,"webViewUrl":null,"floorPlanUrl":null,"location":{"longitude":"-0.110252","latitude":"51.480401"},"timeZone":"Europe/London","reopenDate":"2021-04-12T00:00:00+01 Europe/London"}"""
let oval =
{
Gym.Name = "London Oval"
Id = 19
Status = 2
Address =
{
AddressLine1 = "Canterbury Court"
AddressLine2 = Some "Units 4, 4A, 5 And 5A"
AddressLine3 = Some "Kennington Park"
Town = "LONDON"
County = None
Postcode = "SW9 6DE"
}
PhoneNumber = "+44 3444770005"
EmailAddress = "info.londonoval@puregym.com"
GymOpeningHours =
{
IsAlwaysOpen = true
OpeningHours = []
}
AccessOptions = { PinAccess = true ; QrCodeAccess = true }
Location = { Longitude = -0.110252 ; Latitude = 51.480401 }
TimeZone = "Europe/London"
ReopenDate = "2021-04-12T00:00:00+01 Europe/London"
}
[
ovalJson, oval
]
|> List.map TestCaseData
[<TestCaseSource (nameof(gymCases))>]
let ``Gym JSON parse`` (json : string, expected : Gym) =
JsonNode.Parse json
|> Gym.jsonParse
|> shouldEqual expected
let memberCases =
let me =
{
Id = 1234567
CompoundMemberId = "12A123456"
FirstName = "Patrick"
LastName = "Stevens"
HomeGymId = 19
HomeGymName = "London Oval"
EmailAddress = "someone@somewhere"
GymAccessPin = "00000000"
DateOfBirth = DateOnly (1994, 01, 02)
MobileNumber = "+44 1234567"
Postcode = "W1A 1AA"
MembershipName = "Corporate"
MembershipLevel = 12
SuspendedReason = 0
MemberStatus = 2
}
let meJson = """{
"id": 1234567,
"compoundMemberId": "12A123456",
"firstName": "Patrick",
"lastName": "Stevens",
"homeGymId": 19,
"homeGymName": "London Oval",
"emailAddress": "someone@somewhere",
"gymAccessPin": "00000000",
"dateofBirth": "1994-01-02",
"mobileNumber": "+44 1234567",
"postCode": "W1A 1AA",
"membershipName": "Corporate",
"membershipLevel": 12,
"suspendedReason": 0,
"memberStatus": 2
}"""
[
meJson, me
]
|> List.map TestCaseData
[<TestCaseSource (nameof memberCases)>]
let ``Member JSON parse`` (json : string, expected : Member) =
json
|> JsonNode.Parse
|> Member.jsonParse
|> shouldEqual expected
let gymAttendanceCases =
let json = """{
"description": "65",
"totalPeopleInGym": 65,
"totalPeopleInClasses": 2,
"totalPeopleSuffix": null,
"isApproximate": false,
"attendanceTime": "2023-12-27T18:54:09.5101697",
"lastRefreshed": "2023-12-27T18:54:09.5101697Z",
"lastRefreshedPeopleInClasses": "2023-12-27T18:50:26.0782286Z",
"maximumCapacity": 0
}"""
let expected =
{
Description = "65"
TotalPeopleInGym = 65
TotalPeopleInClasses = 2
TotalPeopleSuffix = None
IsApproximate = false
AttendanceTime = DateTime (2023, 12, 27, 18, 54, 09, 510, 169, DateTimeKind.Utc) + TimeSpan.FromTicks 7L
LastRefreshed = DateTime (2023, 12, 27, 18, 54, 09, 510, 169, DateTimeKind.Utc) + TimeSpan.FromTicks 7L
LastRefreshedPeopleInClasses = DateTime (2023, 12, 27, 18, 50, 26, 078, 228, DateTimeKind.Utc) + TimeSpan.FromTicks 6L
MaximumCapacity = 0
}
[
json, expected
]
|> List.map TestCaseData
[<TestCaseSource (nameof gymAttendanceCases)>]
let ``GymAttendance JSON parse`` (json : string, expected : GymAttendance) =
json
|> JsonNode.Parse
|> GymAttendance.jsonParse
|> shouldEqual expected
let memberActivityDtoCases =
let json = """{"totalDuration":2217,"averageDuration":48,"totalVisits":46,"totalClasses":0,"isEstimated":false,"lastRefreshed":"2023-12-27T19:00:56.0309892Z"}"""
let value = {
TotalDuration = 2217
AverageDuration = 48
TotalVisits = 46
TotalClasses = 0
IsEstimated = false
LastRefreshed = DateTime (2023, 12, 27, 19, 00, 56, 030, 989, DateTimeKind.Utc) + TimeSpan.FromTicks 2L
}
[
json, value
]
|> List.map TestCaseData
[<TestCaseSource (nameof memberActivityDtoCases)>]
let ``MemberActivityDto JSON parse`` (json : string, expected : MemberActivityDto) =
json
|> JsonNode.Parse
|> MemberActivityDto.jsonParse
|> shouldEqual expected
let sessionsCases =
let json = """{
"Summary":{"Total":{"Activities":0,"Visits":10,"Duration":445},"ThisWeek":{"Activities":0,"Visits":0,"Duration":0}},
"Visits":[
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-21T10:12:00","Duration":50,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-20T12:05:00","Duration":80,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-17T19:37:00","Duration":46,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-16T12:19:00","Duration":37,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-15T11:14:00","Duration":47,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-13T10:30:00","Duration":36,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-10T16:18:00","Duration":32,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-05T22:36:00","Duration":40,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-03T17:59:00","Duration":48,"Name":null},
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-01T21:41:00","Duration":29,"Name":null}],
"Activities":[]}
"""
let singleVisit startTime duration =
{
IsDurationEstimated = false
Gym = {
Id = 19
Name = "London Oval"
Status = "Blocked"
}
StartTime = startTime
Duration = duration
}
let expected = {
Summary = {
Total = {
Activities = 0
Visits = 10
Duration = 445
}
ThisWeek = {
Activities = 0
Visits = 0
Duration = 0
}
}
Visits =
[
singleVisit (DateTime (2023, 12, 21, 10, 12, 00)) 50
singleVisit (DateTime (2023, 12, 20, 12, 05, 00)) 80
singleVisit (DateTime (2023, 12, 17, 19, 37, 00)) 46
singleVisit (DateTime (2023, 12, 16, 12, 19, 00)) 37
singleVisit (DateTime (2023, 12, 15, 11, 14, 00)) 47
singleVisit (DateTime (2023, 12, 13, 10, 30, 00)) 36
singleVisit (DateTime (2023, 12, 10, 16, 18, 00)) 32
singleVisit (DateTime (2023, 12, 05, 22, 36, 00)) 40
singleVisit (DateTime (2023, 12, 03, 17, 59, 00)) 48
singleVisit (DateTime (2023, 12, 01, 21, 41, 00)) 29
]
}
[
json, expected
]
|> List.map TestCaseData
[<TestCaseSource (nameof sessionsCases)>]
let ``Sessions JSON parse`` (json : string, expected : Sessions) =
json
|> fun o -> JsonNode.Parse (o, Nullable (JsonNodeOptions (PropertyNameCaseInsensitive = true)))
|> Sessions.jsonParse
|> shouldEqual expected

View File

@@ -6,6 +6,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "PureGym.App", "PureGym.App\
EndProject EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "PureGym.Test", "PureGym.Test\PureGym.Test.fsproj", "{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}" Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "PureGym.Test", "PureGym.Test\PureGym.Test.fsproj", "{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}"
EndProject EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MyriadPlugin", "..\MyriadPlugin\MyriadPlugin\MyriadPlugin.fsproj", "{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -24,5 +26,9 @@ Global
{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Release|Any CPU.Build.0 = Release|Any CPU {F09DF609-5F53-4BB3-BD64-DDB136CD4D2E}.Release|Any CPU.Build.0 = Release|Any CPU
{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D1BEE42-EA5E-4F1B-8CDA-37846E68D76E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

58
PureGym/Client.fs Normal file
View File

@@ -0,0 +1,58 @@
namespace PureGym
open System
open System.Net.Http
open System.Threading.Tasks
open RestEase
/// The PureGym REST API. You probably want to instantiate one of these with `Api.make`.
[<Header("User-Agent", "PureGym/1523 CFNetwork/1312 Darwin/21.0.0")>]
type IPureGymApi =
/// Get the complete list of all gyms known to PureGym.
[<Get "v1/gyms/">]
abstract GetGyms : unit -> Task<Gym list>
/// Get information about the PureGym human whose credentials this client is authenticated with.
[<Get "v1/member">]
abstract GetMember : unit -> Task<Member>
/// Get information about how full the given gym currently is. The gym ID can be found from `GetGyms`.
[<Get "v1/gyms/{gym_id}/attendance">]
abstract GetGymAttendance : [<Path "gym_id">] gymId : int -> Task<GymAttendance>
/// Get information about a specific gym.
[<Get "v1/gyms/{gym_id}">]
abstract GetGym : [<Path "gym_id">] gymId : int -> Task<Gym>
/// Get information about the activities logged against the currently authenticated PureGym human.
[<Get "v1/member/activity">]
abstract GetMemberActivity : unit -> Task<MemberActivityThisMonth>
/// Get information about the individual visits to all PureGyms the currently-authenticated PureGym human has made.
[<Get "v2/gymSessions/member">]
abstract GetSessions : [<Query>] fromDate : DateTime -> [<Query>] toDate : DateTime -> Task<Sessions>
// [<Get "v1/member/activity/history">]
// abstract GetMemberActivityAll : unit -> Task<string>
/// Methods for interacting with the PureGym REST API.
[<RequireQualifiedAccess>]
module Dto =
/// Create a REST client, authenticated as the specified user.
let make (auth : Auth) : IPureGymApi Task =
task {
let! token =
match auth with
| Auth.Token t -> Task.FromResult<_> t
| Auth.User cred -> AuthToken.get cred
let client = new HttpClient ()
client.BaseAddress <- Uri "https://capi.puregym.com/api"
client.DefaultRequestHeaders.Authorization <-
Headers.AuthenticationHeaderValue ("Bearer", token.AccessToken)
client.DefaultRequestHeaders.Add ("User-Agent", "PureGym/1523 CFNetwork/1312 Darwin/21.0.0")
return RestClient.For<IPureGymApi> client
}

View File

@@ -1,12 +1,10 @@
namespace PureGym namespace PureGym
open System open System
open System.Net.Http
open System.Text.Json.Serialization open System.Text.Json.Serialization
open System.Threading.Tasks
open RestEase
/// Describes the opening hours of a given gym. /// Describes the opening hours of a given gym.
[<MyriadPlugin.JsonParse>]
type GymOpeningHours = type GymOpeningHours =
{ {
/// If this is true, there should be no OpeningHours (but nothing enforces that). /// If this is true, there should be no OpeningHours (but nothing enforces that).
@@ -23,6 +21,7 @@ type GymOpeningHours =
this.OpeningHours |> String.concat ", " this.OpeningHours |> String.concat ", "
/// How a human can authenticate with a gym when they physically try to enter it /// How a human can authenticate with a gym when they physically try to enter it
[<MyriadPlugin.JsonParse>]
type GymAccessOptions = type GymAccessOptions =
{ {
/// This gym has PIN entry pads /// This gym has PIN entry pads
@@ -36,28 +35,32 @@ type GymAccessOptions =
$"Pin access: %c{Char.emoji this.PinAccess}; QR code access: %c{Char.emoji this.QrCodeAccess}" $"Pin access: %c{Char.emoji this.PinAccess}; QR code access: %c{Char.emoji this.QrCodeAccess}"
/// Where a gym is on the Earth /// Where a gym is on the Earth
[<MyriadPlugin.JsonParse>]
type GymLocation = type GymLocation =
{ {
/// Measured in degrees /// Measured in degrees
[<JsonNumberHandling (JsonNumberHandling.AllowReadingFromString)>]
Longitude : float Longitude : float
/// Measured in degrees /// Measured in degrees
[<JsonNumberHandling (JsonNumberHandling.AllowReadingFromString)>]
Latitude : float Latitude : float
} }
/// The postal address of a gym /// The postal address of a gym
[<MyriadPlugin.JsonParse>]
type GymAddress = type GymAddress =
{ {
/// E.g. "Canterbury Court" /// E.g. "Canterbury Court"
[<JsonRequired>] [<JsonRequired>]
AddressLine1 : string AddressLine1 : string
/// E.g. "Units 4, 4A, 5 And 5A" /// E.g. "Units 4, 4A, 5 And 5A"
AddressLine2 : string AddressLine2 : string option
/// E.g. "Kennington Park" /// E.g. "Kennington Park"
AddressLine3 : string AddressLine3 : string option
/// E.g. "LONDON" /// E.g. "LONDON"
[<JsonRequired>] [<JsonRequired>]
Town : string Town : string
County : string County : string option
/// E.g. "SW9 6DE" /// E.g. "SW9 6DE"
[<JsonRequired>] [<JsonRequired>]
Postcode : string Postcode : string
@@ -67,11 +70,11 @@ type GymAddress =
override this.ToString () = override this.ToString () =
[ [
yield Some this.AddressLine1 yield Some this.AddressLine1
yield this.AddressLine2 |> Option.ofObj yield this.AddressLine2
yield this.AddressLine3 |> Option.ofObj yield this.AddressLine3
match this.County with match this.County with
| null -> yield Some $"%s{this.Town} %s{this.Postcode}" | None -> yield Some $"%s{this.Town} %s{this.Postcode}"
| county -> | Some county ->
yield Some this.Town yield Some this.Town
yield Some $"%s{county} %s{this.Postcode}" yield Some $"%s{county} %s{this.Postcode}"
] ]
@@ -79,6 +82,7 @@ type GymAddress =
|> String.concat "\n" |> String.concat "\n"
/// Metadata about a physical gym /// Metadata about a physical gym
[<MyriadPlugin.JsonParse>]
type Gym = type Gym =
{ {
// The following fields are returned but are always null // The following fields are returned but are always null
@@ -133,6 +137,7 @@ Opening hours: %s{string<GymOpeningHours> this.GymOpeningHours}
""" """
/// A human member of PureGym /// A human member of PureGym
[<MyriadPlugin.JsonParse>]
type Member = type Member =
{ {
/// This member's ID. This is a fairly large number. /// This member's ID. This is a fairly large number.
@@ -153,10 +158,12 @@ type Member =
/// This user's gym access pin, probably 8 digits /// This user's gym access pin, probably 8 digits
GymAccessPin : string GymAccessPin : string
/// This user's recorded date of birth /// This user's recorded date of birth
[<JsonPropertyName "dateofBirth">]
DateOfBirth : DateOnly DateOfBirth : DateOnly
/// This user's phone number, human-readable /// This user's phone number, human-readable
MobileNumber : string MobileNumber : string
/// This user's registered home postcode /// This user's registered home postcode
[<JsonPropertyName "postCode">]
Postcode : string Postcode : string
/// E.g. "Corporate" /// E.g. "Corporate"
MembershipName : string MembershipName : string
@@ -166,6 +173,7 @@ type Member =
} }
/// Statistics for how many people are currently at a gym /// Statistics for how many people are currently at a gym
[<MyriadPlugin.JsonParse>]
type GymAttendance = type GymAttendance =
{ {
/// This appears always to be just equal to TotalPeopleInGym, but a string. /// This appears always to be just equal to TotalPeopleInGym, but a string.
@@ -178,7 +186,7 @@ type GymAttendance =
[<JsonRequired>] [<JsonRequired>]
TotalPeopleInClasses : int TotalPeopleInClasses : int
/// E.g. " or fewer" /// E.g. " or fewer"
TotalPeopleSuffix : string TotalPeopleSuffix : string option
[<JsonRequired>] [<JsonRequired>]
IsApproximate : bool IsApproximate : bool
/// When the query was received (I think) /// When the query was received (I think)
@@ -195,8 +203,8 @@ type GymAttendance =
override this.ToString () = override this.ToString () =
let totalPeopleSuffix = let totalPeopleSuffix =
match this.TotalPeopleSuffix with match this.TotalPeopleSuffix with
| null -> "" | None -> ""
| suffix -> suffix | Some suffix -> suffix
let capacity = let capacity =
if this.MaximumCapacity = 0 then if this.MaximumCapacity = 0 then
@@ -234,6 +242,7 @@ type MemberActivityThisMonth =
} }
/// Don't use this type. It's public because System.Text.Json can't do private types. /// Don't use this type. It's public because System.Text.Json can't do private types.
[<MyriadPlugin.JsonParse>]
type MemberActivityDto = type MemberActivityDto =
{ {
[<JsonRequired>] [<JsonRequired>]
@@ -260,6 +269,7 @@ type MemberActivityDto =
LastRefreshed = this.LastRefreshed LastRefreshed = this.LastRefreshed
} }
[<MyriadPlugin.JsonParse>]
type SessionsAggregate = type SessionsAggregate =
{ {
/// Number of gym "activities" within some query-defined time period; presumably this is like classes? /// Number of gym "activities" within some query-defined time period; presumably this is like classes?
@@ -272,6 +282,7 @@ type SessionsAggregate =
} }
/// The DTO for gym info returned from the Sessions endpoint. /// The DTO for gym info returned from the Sessions endpoint.
[<MyriadPlugin.JsonParse>]
type VisitGym = type VisitGym =
{ {
// Omitting Location, GymAccess, ContactInfo, TimeZone because these were all null for me // Omitting Location, GymAccess, ContactInfo, TimeZone because these were all null for me
@@ -284,6 +295,7 @@ type VisitGym =
} }
/// Summary of a single visit to a gym. /// Summary of a single visit to a gym.
[<MyriadPlugin.JsonParse>]
type Visit = type Visit =
{ {
// Omitted Name because it always was null for me // Omitted Name because it always was null for me
@@ -303,6 +315,7 @@ type Visit =
$"%s{this.Gym.Name}: %s{startTime} (%i{this.Duration} minutes)" $"%s{this.Gym.Name}: %s{startTime} (%i{this.Duration} minutes)"
/// Aggregate statistics for gym visits across a time period. /// Aggregate statistics for gym visits across a time period.
[<MyriadPlugin.JsonParse>]
type SessionsSummary = type SessionsSummary =
{ {
/// Aggregate stats for gym visits within the query-dependent time period. /// Aggregate stats for gym visits within the query-dependent time period.
@@ -315,6 +328,7 @@ type SessionsSummary =
override this.ToString () = override this.ToString () =
$"%i{this.Total.Visits} visits, totalling %i{this.Total.Duration} minutes" $"%i{this.Total.Visits} visits, totalling %i{this.Total.Duration} minutes"
[<MyriadPlugin.JsonParse>]
type Sessions = type Sessions =
{ {
Summary : SessionsSummary Summary : SessionsSummary
@@ -327,55 +341,3 @@ type Sessions =
let visits = this.Visits |> Seq.map string<Visit> |> String.concat "\n" let visits = this.Visits |> Seq.map string<Visit> |> String.concat "\n"
$"%s{summary}\n%s{visits}" $"%s{summary}\n%s{visits}"
/// The PureGym REST API. You probably want to instantiate one of these with `Api.make`.
[<Header("User-Agent", "PureGym/1523 CFNetwork/1312 Darwin/21.0.0")>]
type IPureGymApi =
/// Get the complete list of all gyms known to PureGym.
[<Get "v1/gyms/">]
abstract GetGyms : unit -> Task<Gym list>
/// Get information about the PureGym human whose credentials this client is authenticated with.
[<Get "v1/member">]
abstract GetMember : unit -> Task<Member>
/// Get information about how full the given gym currently is. The gym ID can be found from `GetGyms`.
[<Get "v1/gyms/{gym_id}/attendance">]
abstract GetGymAttendance : [<Path "gym_id">] gymId : int -> Task<GymAttendance>
/// Get information about a specific gym.
[<Get "v1/gyms/{gym_id}">]
abstract GetGym : [<Path "gym_id">] gymId : int -> Task<Gym>
/// Get information about the activities logged against the currently authenticated PureGym human.
[<Get "v1/member/activity">]
abstract GetMemberActivity : unit -> Task<MemberActivityDto>
/// Get information about the individual visits to all PureGyms the currently-authenticated PureGym human has made.
[<Get "v2/gymSessions/member">]
abstract GetSessions : [<Query>] fromDate : DateTime -> [<Query>] toDate : DateTime -> Task<Sessions>
// [<Get "v1/member/activity/history">]
// abstract GetMemberActivityAll : unit -> Task<string>
/// Methods for interacting with the PureGym REST API.
[<RequireQualifiedAccess>]
module Api =
/// Create a REST client, authenticated as the specified user.
let make (auth : Auth) : IPureGymApi Task =
task {
let! token =
match auth with
| Auth.Token t -> Task.FromResult<_> t
| Auth.User cred -> AuthToken.get cred
let client = new HttpClient ()
client.BaseAddress <- Uri "https://capi.puregym.com/api"
client.DefaultRequestHeaders.Authorization <-
Headers.AuthenticationHeaderValue ("Bearer", token.AccessToken)
client.DefaultRequestHeaders.Add ("User-Agent", "PureGym/1523 CFNetwork/1312 Darwin/21.0.0")
return RestClient.For<IPureGymApi> client
}

321
PureGym/GeneratedDto.fs Normal file
View File

@@ -0,0 +1,321 @@
//------------------------------------------------------------------------------
// This code was generated by myriad.
// Changes to this file will be lost when the code is regenerated.
//------------------------------------------------------------------------------
namespace PureGym
/// Module containing JSON parsing methods for the GymOpeningHours type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymOpeningHours =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymOpeningHours =
let OpeningHours =
node.["openingHours"].AsArray()
|> Seq.map (fun elt -> elt.AsValue().GetValue<string>())
|> List.ofSeq
let IsAlwaysOpen = node.["isAlwaysOpen"].AsValue().GetValue<bool>()
{ IsAlwaysOpen = IsAlwaysOpen
OpeningHours = OpeningHours }
namespace PureGym
/// Module containing JSON parsing methods for the GymAccessOptions type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymAccessOptions =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymAccessOptions =
let QrCodeAccess = node.["qrCodeAccess"].AsValue().GetValue<bool>()
let PinAccess = node.["pinAccess"].AsValue().GetValue<bool>()
{ PinAccess = PinAccess
QrCodeAccess = QrCodeAccess }
namespace PureGym
/// Module containing JSON parsing methods for the GymLocation type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymLocation =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymLocation =
let Latitude =
try
node.["latitude"].AsValue().GetValue<float>()
with :? System.InvalidOperationException as exc ->
if exc.Message.Contains "cannot be converted to" then
if
System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString
then
node.["latitude"].AsValue().GetValue<string>() |> System.Double.Parse
else
reraise ()
else
reraise ()
let Longitude =
try
node.["longitude"].AsValue().GetValue<float>()
with :? System.InvalidOperationException as exc ->
if exc.Message.Contains "cannot be converted to" then
if
System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString
then
node.["longitude"].AsValue().GetValue<string>() |> System.Double.Parse
else
reraise ()
else
reraise ()
{ Longitude = Longitude
Latitude = Latitude }
namespace PureGym
/// Module containing JSON parsing methods for the GymAddress type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymAddress =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymAddress =
let Postcode = node.["postcode"].AsValue().GetValue<string>()
let County =
match node.["county"] with
| null -> None
| v -> v.AsValue().GetValue<string>() |> Some
let Town = node.["town"].AsValue().GetValue<string>()
let AddressLine3 =
match node.["addressLine3"] with
| null -> None
| v -> v.AsValue().GetValue<string>() |> Some
let AddressLine2 =
match node.["addressLine2"] with
| null -> None
| v -> v.AsValue().GetValue<string>() |> Some
let AddressLine1 = node.["addressLine1"].AsValue().GetValue<string>()
{ AddressLine1 = AddressLine1
AddressLine2 = AddressLine2
AddressLine3 = AddressLine3
Town = Town
County = County
Postcode = Postcode }
namespace PureGym
/// Module containing JSON parsing methods for the Gym type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Gym =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : Gym =
let ReopenDate = node.["reopenDate"].AsValue().GetValue<string>()
let TimeZone = node.["timeZone"].AsValue().GetValue<string>()
let Location = GymLocation.jsonParse node.["location"]
let AccessOptions = GymAccessOptions.jsonParse node.["accessOptions"]
let GymOpeningHours = GymOpeningHours.jsonParse node.["gymOpeningHours"]
let EmailAddress = node.["emailAddress"].AsValue().GetValue<string>()
let PhoneNumber = node.["phoneNumber"].AsValue().GetValue<string>()
let Address = GymAddress.jsonParse node.["address"]
let Status = node.["status"].AsValue().GetValue<int>()
let Id = node.["id"].AsValue().GetValue<int>()
let Name = node.["name"].AsValue().GetValue<string>()
{ Name = Name
Id = Id
Status = Status
Address = Address
PhoneNumber = PhoneNumber
EmailAddress = EmailAddress
GymOpeningHours = GymOpeningHours
AccessOptions = AccessOptions
Location = Location
TimeZone = TimeZone
ReopenDate = ReopenDate }
namespace PureGym
/// Module containing JSON parsing methods for the Member type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Member =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : Member =
let MemberStatus = node.["memberStatus"].AsValue().GetValue<int>()
let SuspendedReason = node.["suspendedReason"].AsValue().GetValue<int>()
let MembershipLevel = node.["membershipLevel"].AsValue().GetValue<int>()
let MembershipName = node.["membershipName"].AsValue().GetValue<string>()
let Postcode = node.["postCode"].AsValue().GetValue<string>()
let MobileNumber = node.["mobileNumber"].AsValue().GetValue<string>()
let DateOfBirth =
node.["dateofBirth"].AsValue().GetValue<string>() |> System.DateOnly.Parse
let GymAccessPin = node.["gymAccessPin"].AsValue().GetValue<string>()
let EmailAddress = node.["emailAddress"].AsValue().GetValue<string>()
let HomeGymName = node.["homeGymName"].AsValue().GetValue<string>()
let HomeGymId = node.["homeGymId"].AsValue().GetValue<int>()
let LastName = node.["lastName"].AsValue().GetValue<string>()
let FirstName = node.["firstName"].AsValue().GetValue<string>()
let CompoundMemberId = node.["compoundMemberId"].AsValue().GetValue<string>()
let Id = node.["id"].AsValue().GetValue<int>()
{ Id = Id
CompoundMemberId = CompoundMemberId
FirstName = FirstName
LastName = LastName
HomeGymId = HomeGymId
HomeGymName = HomeGymName
EmailAddress = EmailAddress
GymAccessPin = GymAccessPin
DateOfBirth = DateOfBirth
MobileNumber = MobileNumber
Postcode = Postcode
MembershipName = MembershipName
MembershipLevel = MembershipLevel
SuspendedReason = SuspendedReason
MemberStatus = MemberStatus }
namespace PureGym
/// Module containing JSON parsing methods for the GymAttendance type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GymAttendance =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : GymAttendance =
let MaximumCapacity = node.["maximumCapacity"].AsValue().GetValue<int>()
let LastRefreshedPeopleInClasses =
node.["lastRefreshedPeopleInClasses"].AsValue().GetValue<string>()
|> System.DateTime.Parse
let LastRefreshed =
node.["lastRefreshed"].AsValue().GetValue<string>() |> System.DateTime.Parse
let AttendanceTime =
node.["attendanceTime"].AsValue().GetValue<string>() |> System.DateTime.Parse
let IsApproximate = node.["isApproximate"].AsValue().GetValue<bool>()
let TotalPeopleSuffix =
match node.["totalPeopleSuffix"] with
| null -> None
| v -> v.AsValue().GetValue<string>() |> Some
let TotalPeopleInClasses = node.["totalPeopleInClasses"].AsValue().GetValue<int>()
let TotalPeopleInGym = node.["totalPeopleInGym"].AsValue().GetValue<int>()
let Description = node.["description"].AsValue().GetValue<string>()
{ Description = Description
TotalPeopleInGym = TotalPeopleInGym
TotalPeopleInClasses = TotalPeopleInClasses
TotalPeopleSuffix = TotalPeopleSuffix
IsApproximate = IsApproximate
AttendanceTime = AttendanceTime
LastRefreshed = LastRefreshed
LastRefreshedPeopleInClasses = LastRefreshedPeopleInClasses
MaximumCapacity = MaximumCapacity }
namespace PureGym
/// Module containing JSON parsing methods for the MemberActivityDto type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module MemberActivityDto =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : MemberActivityDto =
let LastRefreshed =
node.["lastRefreshed"].AsValue().GetValue<string>() |> System.DateTime.Parse
let IsEstimated = node.["isEstimated"].AsValue().GetValue<bool>()
let TotalClasses = node.["totalClasses"].AsValue().GetValue<int>()
let TotalVisits = node.["totalVisits"].AsValue().GetValue<int>()
let AverageDuration = node.["averageDuration"].AsValue().GetValue<int>()
let TotalDuration = node.["totalDuration"].AsValue().GetValue<int>()
{ TotalDuration = TotalDuration
AverageDuration = AverageDuration
TotalVisits = TotalVisits
TotalClasses = TotalClasses
IsEstimated = IsEstimated
LastRefreshed = LastRefreshed }
namespace PureGym
/// Module containing JSON parsing methods for the SessionsAggregate type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module SessionsAggregate =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
let Duration = node.["duration"].AsValue().GetValue<int>()
let Visits = node.["visits"].AsValue().GetValue<int>()
let Activities = node.["activities"].AsValue().GetValue<int>()
{ Activities = Activities
Visits = Visits
Duration = Duration }
namespace PureGym
/// Module containing JSON parsing methods for the VisitGym type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module VisitGym =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : VisitGym =
let Status = node.["status"].AsValue().GetValue<string>()
let Name = node.["name"].AsValue().GetValue<string>()
let Id = node.["id"].AsValue().GetValue<int>()
{ Id = Id
Name = Name
Status = Status }
namespace PureGym
/// Module containing JSON parsing methods for the Visit type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Visit =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : Visit =
let Gym = VisitGym.jsonParse node.["gym"]
let Duration = node.["duration"].AsValue().GetValue<int>()
let StartTime =
node.["startTime"].AsValue().GetValue<string>() |> System.DateTime.Parse
let IsDurationEstimated = node.["isDurationEstimated"].AsValue().GetValue<bool>()
{ IsDurationEstimated = IsDurationEstimated
StartTime = StartTime
Duration = Duration
Gym = Gym }
namespace PureGym
/// Module containing JSON parsing methods for the SessionsSummary type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module SessionsSummary =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : SessionsSummary =
let ThisWeek = SessionsAggregate.jsonParse node.["thisWeek"]
let Total = SessionsAggregate.jsonParse node.["total"]
{ Total = Total; ThisWeek = ThisWeek }
namespace PureGym
/// Module containing JSON parsing methods for the Sessions type
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Sessions =
/// Parse from a JSON node.
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : Sessions =
let Visits =
node.["visits"].AsArray()
|> Seq.map (fun elt -> Visit.jsonParse elt)
|> List.ofSeq
let Summary = SessionsSummary.jsonParse node.["summary"]
{ Summary = Summary; Visits = Visits }

View File

@@ -8,17 +8,30 @@
<ItemGroup> <ItemGroup>
<Compile Include="String.fs" /> <Compile Include="String.fs" />
<Compile Include="Auth.fs" /> <Compile Include="Auth.fs" />
<Compile Include="Api.fs" /> <Compile Include="Dto.fs" />
<Compile Include="GeneratedDto.fs"> <!--1-->
<MyriadFile>Dto.fs</MyriadFile> <!--2-->
</Compile>
<Compile Include="Client.fs" />
<Compile Include="GymSelector.fs" /> <Compile Include="GymSelector.fs" />
<EmbeddedResource Include="SurfaceBaseline.txt" /> <EmbeddedResource Include="SurfaceBaseline.txt" />
<EmbeddedResource Include="version.json" /> <EmbeddedResource Include="version.json" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<MyriadSdkGenerator Include="/Users/patrick/Documents/GitHub/MyriadPlugin/MyriadPlugin/bin/Debug/net6.0/MyriadPlugin.dll" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RestEase" Version="1.6.4" /> <PackageReference Include="RestEase" Version="1.6.4" />
<PackageReference Update="FSharp.Core" Version="6.0.0" /> <PackageReference Update="FSharp.Core" Version="6.0.1" />
<PackageReference Include="System.Text.Json" Version="7.0.3" /> <PackageReference Include="System.Text.Json" Version="7.0.3" />
<PackageReference Include="Fastenshtein" Version="1.0.0.8" /> <PackageReference Include="Fastenshtein" Version="1.0.0.8" />
<PackageReference Include="Myriad.Core" Version="0.8.3" />
<PackageReference Include="Myriad.Sdk" Version="0.8.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MyriadPlugin\MyriadPlugin\MyriadPlugin.fsproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,5 +1,3 @@
PureGym.Api inherit obj
PureGym.Api.make [static method]: PureGym.Auth -> PureGym.IPureGymApi System.Threading.Tasks.Task
PureGym.Auth inherit obj, implements PureGym.Auth System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Auth System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases PureGym.Auth inherit obj, implements PureGym.Auth System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Auth System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
PureGym.Auth+Tags inherit obj PureGym.Auth+Tags inherit obj
PureGym.Auth+Tags.Token [static field]: int = 1 PureGym.Auth+Tags.Token [static field]: int = 1
@@ -37,6 +35,8 @@ PureGym.AuthToken.get_ExpiryTime [method]: unit -> System.DateTime option
PureGym.AuthTokenModule inherit obj PureGym.AuthTokenModule inherit obj
PureGym.AuthTokenModule.get [static method]: PureGym.UsernamePin -> PureGym.AuthToken System.Threading.Tasks.Task PureGym.AuthTokenModule.get [static method]: PureGym.UsernamePin -> PureGym.AuthToken System.Threading.Tasks.Task
PureGym.AuthTokenModule.ofBearerToken [static method]: string -> PureGym.AuthToken PureGym.AuthTokenModule.ofBearerToken [static method]: string -> PureGym.AuthToken
PureGym.Dto inherit obj
PureGym.Dto.make [static method]: PureGym.Auth -> PureGym.IPureGymApi System.Threading.Tasks.Task
PureGym.Gym inherit obj, implements PureGym.Gym System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Gym System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.Gym inherit obj, implements PureGym.Gym System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Gym System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.Gym..ctor [constructor]: (string, int, int, PureGym.GymAddress, string, string, PureGym.GymOpeningHours, PureGym.GymAccessOptions, PureGym.GymLocation, string, string) PureGym.Gym..ctor [constructor]: (string, int, int, PureGym.GymAddress, string, string, PureGym.GymOpeningHours, PureGym.GymAccessOptions, PureGym.GymLocation, string, string)
PureGym.Gym.AccessOptions [property]: [read-only] PureGym.GymAccessOptions PureGym.Gym.AccessOptions [property]: [read-only] PureGym.GymAccessOptions
@@ -67,22 +67,26 @@ PureGym.GymAccessOptions.get_PinAccess [method]: unit -> bool
PureGym.GymAccessOptions.get_QrCodeAccess [method]: unit -> bool PureGym.GymAccessOptions.get_QrCodeAccess [method]: unit -> bool
PureGym.GymAccessOptions.PinAccess [property]: [read-only] bool PureGym.GymAccessOptions.PinAccess [property]: [read-only] bool
PureGym.GymAccessOptions.QrCodeAccess [property]: [read-only] bool PureGym.GymAccessOptions.QrCodeAccess [property]: [read-only] bool
PureGym.GymAccessOptionsModule inherit obj
PureGym.GymAccessOptionsModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymAccessOptions
PureGym.GymAddress inherit obj, implements PureGym.GymAddress System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymAddress System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.GymAddress inherit obj, implements PureGym.GymAddress System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymAddress System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.GymAddress..ctor [constructor]: (string, string, string, string, string, string) PureGym.GymAddress..ctor [constructor]: (string, string option, string option, string, string option, string)
PureGym.GymAddress.AddressLine1 [property]: [read-only] string PureGym.GymAddress.AddressLine1 [property]: [read-only] string
PureGym.GymAddress.AddressLine2 [property]: [read-only] string PureGym.GymAddress.AddressLine2 [property]: [read-only] string option
PureGym.GymAddress.AddressLine3 [property]: [read-only] string PureGym.GymAddress.AddressLine3 [property]: [read-only] string option
PureGym.GymAddress.County [property]: [read-only] string PureGym.GymAddress.County [property]: [read-only] string option
PureGym.GymAddress.get_AddressLine1 [method]: unit -> string PureGym.GymAddress.get_AddressLine1 [method]: unit -> string
PureGym.GymAddress.get_AddressLine2 [method]: unit -> string PureGym.GymAddress.get_AddressLine2 [method]: unit -> string option
PureGym.GymAddress.get_AddressLine3 [method]: unit -> string PureGym.GymAddress.get_AddressLine3 [method]: unit -> string option
PureGym.GymAddress.get_County [method]: unit -> string PureGym.GymAddress.get_County [method]: unit -> string option
PureGym.GymAddress.get_Postcode [method]: unit -> string PureGym.GymAddress.get_Postcode [method]: unit -> string
PureGym.GymAddress.get_Town [method]: unit -> string PureGym.GymAddress.get_Town [method]: unit -> string
PureGym.GymAddress.Postcode [property]: [read-only] string PureGym.GymAddress.Postcode [property]: [read-only] string
PureGym.GymAddress.Town [property]: [read-only] string PureGym.GymAddress.Town [property]: [read-only] string
PureGym.GymAddressModule inherit obj
PureGym.GymAddressModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymAddress
PureGym.GymAttendance inherit obj, implements PureGym.GymAttendance System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymAttendance System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.GymAttendance inherit obj, implements PureGym.GymAttendance System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymAttendance System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.GymAttendance..ctor [constructor]: (string, int, int, string, bool, System.DateTime, System.DateTime, System.DateTime, int) PureGym.GymAttendance..ctor [constructor]: (string, int, int, string option, bool, System.DateTime, System.DateTime, System.DateTime, int)
PureGym.GymAttendance.AttendanceTime [property]: [read-only] System.DateTime PureGym.GymAttendance.AttendanceTime [property]: [read-only] System.DateTime
PureGym.GymAttendance.Description [property]: [read-only] string PureGym.GymAttendance.Description [property]: [read-only] string
PureGym.GymAttendance.get_AttendanceTime [method]: unit -> System.DateTime PureGym.GymAttendance.get_AttendanceTime [method]: unit -> System.DateTime
@@ -93,26 +97,34 @@ PureGym.GymAttendance.get_LastRefreshedPeopleInClasses [method]: unit -> System.
PureGym.GymAttendance.get_MaximumCapacity [method]: unit -> int PureGym.GymAttendance.get_MaximumCapacity [method]: unit -> int
PureGym.GymAttendance.get_TotalPeopleInClasses [method]: unit -> int PureGym.GymAttendance.get_TotalPeopleInClasses [method]: unit -> int
PureGym.GymAttendance.get_TotalPeopleInGym [method]: unit -> int PureGym.GymAttendance.get_TotalPeopleInGym [method]: unit -> int
PureGym.GymAttendance.get_TotalPeopleSuffix [method]: unit -> string PureGym.GymAttendance.get_TotalPeopleSuffix [method]: unit -> string option
PureGym.GymAttendance.IsApproximate [property]: [read-only] bool PureGym.GymAttendance.IsApproximate [property]: [read-only] bool
PureGym.GymAttendance.LastRefreshed [property]: [read-only] System.DateTime PureGym.GymAttendance.LastRefreshed [property]: [read-only] System.DateTime
PureGym.GymAttendance.LastRefreshedPeopleInClasses [property]: [read-only] System.DateTime PureGym.GymAttendance.LastRefreshedPeopleInClasses [property]: [read-only] System.DateTime
PureGym.GymAttendance.MaximumCapacity [property]: [read-only] int PureGym.GymAttendance.MaximumCapacity [property]: [read-only] int
PureGym.GymAttendance.TotalPeopleInClasses [property]: [read-only] int PureGym.GymAttendance.TotalPeopleInClasses [property]: [read-only] int
PureGym.GymAttendance.TotalPeopleInGym [property]: [read-only] int PureGym.GymAttendance.TotalPeopleInGym [property]: [read-only] int
PureGym.GymAttendance.TotalPeopleSuffix [property]: [read-only] string PureGym.GymAttendance.TotalPeopleSuffix [property]: [read-only] string option
PureGym.GymAttendanceModule inherit obj
PureGym.GymAttendanceModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymAttendance
PureGym.GymLocation inherit obj, implements PureGym.GymLocation System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymLocation System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.GymLocation inherit obj, implements PureGym.GymLocation System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymLocation System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.GymLocation..ctor [constructor]: (float, float) PureGym.GymLocation..ctor [constructor]: (float, float)
PureGym.GymLocation.get_Latitude [method]: unit -> float PureGym.GymLocation.get_Latitude [method]: unit -> float
PureGym.GymLocation.get_Longitude [method]: unit -> float PureGym.GymLocation.get_Longitude [method]: unit -> float
PureGym.GymLocation.Latitude [property]: [read-only] float PureGym.GymLocation.Latitude [property]: [read-only] float
PureGym.GymLocation.Longitude [property]: [read-only] float PureGym.GymLocation.Longitude [property]: [read-only] float
PureGym.GymLocationModule inherit obj
PureGym.GymLocationModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymLocation
PureGym.GymModule inherit obj
PureGym.GymModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.Gym
PureGym.GymOpeningHours inherit obj, implements PureGym.GymOpeningHours System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymOpeningHours System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.GymOpeningHours inherit obj, implements PureGym.GymOpeningHours System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymOpeningHours System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.GymOpeningHours..ctor [constructor]: (bool, string list) PureGym.GymOpeningHours..ctor [constructor]: (bool, string list)
PureGym.GymOpeningHours.get_IsAlwaysOpen [method]: unit -> bool PureGym.GymOpeningHours.get_IsAlwaysOpen [method]: unit -> bool
PureGym.GymOpeningHours.get_OpeningHours [method]: unit -> string list PureGym.GymOpeningHours.get_OpeningHours [method]: unit -> string list
PureGym.GymOpeningHours.IsAlwaysOpen [property]: [read-only] bool PureGym.GymOpeningHours.IsAlwaysOpen [property]: [read-only] bool
PureGym.GymOpeningHours.OpeningHours [property]: [read-only] string list PureGym.GymOpeningHours.OpeningHours [property]: [read-only] string list
PureGym.GymOpeningHoursModule inherit obj
PureGym.GymOpeningHoursModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.GymOpeningHours
PureGym.GymSelector inherit obj, implements PureGym.GymSelector System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymSelector System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 3 cases PureGym.GymSelector inherit obj, implements PureGym.GymSelector System.IEquatable, System.Collections.IStructuralEquatable, PureGym.GymSelector System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 3 cases
PureGym.GymSelector+Id inherit PureGym.GymSelector PureGym.GymSelector+Id inherit PureGym.GymSelector
PureGym.GymSelector+Id.get_Item [method]: unit -> int PureGym.GymSelector+Id.get_Item [method]: unit -> int
@@ -143,8 +155,8 @@ PureGym.IPureGymApi.GetGym [method]: int -> PureGym.Gym System.Threading.Tasks.T
PureGym.IPureGymApi.GetGymAttendance [method]: int -> PureGym.GymAttendance System.Threading.Tasks.Task PureGym.IPureGymApi.GetGymAttendance [method]: int -> PureGym.GymAttendance System.Threading.Tasks.Task
PureGym.IPureGymApi.GetGyms [method]: unit -> PureGym.Gym list System.Threading.Tasks.Task PureGym.IPureGymApi.GetGyms [method]: unit -> PureGym.Gym list System.Threading.Tasks.Task
PureGym.IPureGymApi.GetMember [method]: unit -> PureGym.Member System.Threading.Tasks.Task PureGym.IPureGymApi.GetMember [method]: unit -> PureGym.Member System.Threading.Tasks.Task
PureGym.IPureGymApi.GetMemberActivity [method]: unit -> PureGym.MemberActivityDto System.Threading.Tasks.Task PureGym.IPureGymApi.GetMemberActivity [method]: unit -> string System.Threading.Tasks.Task
PureGym.IPureGymApi.GetSessions [method]: System.DateTime -> System.DateTime -> PureGym.Sessions System.Threading.Tasks.Task PureGym.IPureGymApi.GetSessions [method]: System.DateTime -> System.DateTime -> string System.Threading.Tasks.Task
PureGym.Member inherit obj, implements PureGym.Member System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Member System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.Member inherit obj, implements PureGym.Member System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Member System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.Member..ctor [constructor]: (int, string, string, string, int, string, string, string, System.DateOnly, string, string, string, int, int, int) PureGym.Member..ctor [constructor]: (int, string, string, string, int, string, string, string, System.DateOnly, string, string, string, int, int, int)
PureGym.Member.CompoundMemberId [property]: [read-only] string PureGym.Member.CompoundMemberId [property]: [read-only] string
@@ -192,6 +204,8 @@ PureGym.MemberActivityDto.ToMemberActivity [method]: unit -> PureGym.MemberActiv
PureGym.MemberActivityDto.TotalClasses [property]: [read-only] int PureGym.MemberActivityDto.TotalClasses [property]: [read-only] int
PureGym.MemberActivityDto.TotalDuration [property]: [read-only] int PureGym.MemberActivityDto.TotalDuration [property]: [read-only] int
PureGym.MemberActivityDto.TotalVisits [property]: [read-only] int PureGym.MemberActivityDto.TotalVisits [property]: [read-only] int
PureGym.MemberActivityDtoModule inherit obj
PureGym.MemberActivityDtoModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.MemberActivityDto
PureGym.MemberActivityThisMonth inherit obj, implements PureGym.MemberActivityThisMonth System.IEquatable, System.Collections.IStructuralEquatable, PureGym.MemberActivityThisMonth System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.MemberActivityThisMonth inherit obj, implements PureGym.MemberActivityThisMonth System.IEquatable, System.Collections.IStructuralEquatable, PureGym.MemberActivityThisMonth System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.MemberActivityThisMonth..ctor [constructor]: (int, int, int, int, bool, System.DateTime) PureGym.MemberActivityThisMonth..ctor [constructor]: (int, int, int, int, bool, System.DateTime)
PureGym.MemberActivityThisMonth.AverageDurationMinutes [property]: [read-only] int PureGym.MemberActivityThisMonth.AverageDurationMinutes [property]: [read-only] int
@@ -206,6 +220,8 @@ PureGym.MemberActivityThisMonth.LastRefreshed [property]: [read-only] System.Dat
PureGym.MemberActivityThisMonth.TotalClasses [property]: [read-only] int PureGym.MemberActivityThisMonth.TotalClasses [property]: [read-only] int
PureGym.MemberActivityThisMonth.TotalDurationMinutes [property]: [read-only] int PureGym.MemberActivityThisMonth.TotalDurationMinutes [property]: [read-only] int
PureGym.MemberActivityThisMonth.TotalVisits [property]: [read-only] int PureGym.MemberActivityThisMonth.TotalVisits [property]: [read-only] int
PureGym.MemberModule inherit obj
PureGym.MemberModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.Member
PureGym.Sessions inherit obj, implements PureGym.Sessions System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Sessions System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.Sessions inherit obj, implements PureGym.Sessions System.IEquatable, System.Collections.IStructuralEquatable, PureGym.Sessions System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.Sessions..ctor [constructor]: (PureGym.SessionsSummary, PureGym.Visit list) PureGym.Sessions..ctor [constructor]: (PureGym.SessionsSummary, PureGym.Visit list)
PureGym.Sessions.get_Summary [method]: unit -> PureGym.SessionsSummary PureGym.Sessions.get_Summary [method]: unit -> PureGym.SessionsSummary
@@ -220,12 +236,18 @@ PureGym.SessionsAggregate.get_Activities [method]: unit -> int
PureGym.SessionsAggregate.get_Duration [method]: unit -> int PureGym.SessionsAggregate.get_Duration [method]: unit -> int
PureGym.SessionsAggregate.get_Visits [method]: unit -> int PureGym.SessionsAggregate.get_Visits [method]: unit -> int
PureGym.SessionsAggregate.Visits [property]: [read-only] int PureGym.SessionsAggregate.Visits [property]: [read-only] int
PureGym.SessionsAggregateModule inherit obj
PureGym.SessionsAggregateModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.SessionsAggregate
PureGym.SessionsModule inherit obj
PureGym.SessionsModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.Sessions
PureGym.SessionsSummary inherit obj, implements PureGym.SessionsSummary System.IEquatable, System.Collections.IStructuralEquatable, PureGym.SessionsSummary System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.SessionsSummary inherit obj, implements PureGym.SessionsSummary System.IEquatable, System.Collections.IStructuralEquatable, PureGym.SessionsSummary System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.SessionsSummary..ctor [constructor]: (PureGym.SessionsAggregate, PureGym.SessionsAggregate) PureGym.SessionsSummary..ctor [constructor]: (PureGym.SessionsAggregate, PureGym.SessionsAggregate)
PureGym.SessionsSummary.get_ThisWeek [method]: unit -> PureGym.SessionsAggregate PureGym.SessionsSummary.get_ThisWeek [method]: unit -> PureGym.SessionsAggregate
PureGym.SessionsSummary.get_Total [method]: unit -> PureGym.SessionsAggregate PureGym.SessionsSummary.get_Total [method]: unit -> PureGym.SessionsAggregate
PureGym.SessionsSummary.ThisWeek [property]: [read-only] PureGym.SessionsAggregate PureGym.SessionsSummary.ThisWeek [property]: [read-only] PureGym.SessionsAggregate
PureGym.SessionsSummary.Total [property]: [read-only] PureGym.SessionsAggregate PureGym.SessionsSummary.Total [property]: [read-only] PureGym.SessionsAggregate
PureGym.SessionsSummaryModule inherit obj
PureGym.SessionsSummaryModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.SessionsSummary
PureGym.UsernamePin inherit obj, implements PureGym.UsernamePin System.IEquatable, System.Collections.IStructuralEquatable, PureGym.UsernamePin System.IComparable, System.IComparable, System.Collections.IStructuralComparable PureGym.UsernamePin inherit obj, implements PureGym.UsernamePin System.IEquatable, System.Collections.IStructuralEquatable, PureGym.UsernamePin System.IComparable, System.IComparable, System.Collections.IStructuralComparable
PureGym.UsernamePin..ctor [constructor]: (string, string) PureGym.UsernamePin..ctor [constructor]: (string, string)
PureGym.UsernamePin.get_Pin [method]: unit -> string PureGym.UsernamePin.get_Pin [method]: unit -> string
@@ -250,3 +272,7 @@ PureGym.VisitGym.get_Status [method]: unit -> string
PureGym.VisitGym.Id [property]: [read-only] int PureGym.VisitGym.Id [property]: [read-only] int
PureGym.VisitGym.Name [property]: [read-only] string PureGym.VisitGym.Name [property]: [read-only] string
PureGym.VisitGym.Status [property]: [read-only] string PureGym.VisitGym.Status [property]: [read-only] string
PureGym.VisitGymModule inherit obj
PureGym.VisitGymModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.VisitGym
PureGym.VisitModule inherit obj
PureGym.VisitModule.jsonParse [static method]: System.Text.Json.Nodes.JsonNode -> PureGym.Visit

0
PureGym/myriad.toml Normal file
View File

View File

@@ -1,5 +1,5 @@
{ {
"version": "2.0", "version": "3.0",
"publicReleaseRefSpec": [ "publicReleaseRefSpec": [
"^refs/heads/main$" "^refs/heads/main$"
], ],